knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE, cache = TRUE)

Setup for analysis

Load packages

library(tidyverse) # tidy style coding
library(brms) # Bayesian models
library(loo) # to use information criteria in brms models
library(tidybayes) # Bayesian aesthetics
library(MetBrewer) # colours
library(kableExtra) # tables
library(patchwork) # putting plots together
library(DT) # for search- and saveable tables
library(pander) # for simpler tables

Load in the data

\(~\)

fitness_data <- read_csv("data/SLC_fitness_data.csv") %>% 
  mutate(Fitness_vial_ID = as.factor(Fitness_vial_ID),
         Block = as.factor(Block),
         Population = as.factor(Population),
         Treatment = as.factor(Treatment),
         GFP = as.factor(GFP),
         Sex = as.factor(Sex),
         Rearing_vial = as.factor(Rearing_vial),
         Total_red_offspring = Red_female_offspring + Red_male_offspring,
         Total_bw_offspring = bw_female_offspring + bw_male_offspring,
         Total_offspring = Total_red_offspring + Total_bw_offspring) %>% 
  rename(Evolutionary_treatment = Treatment)

# Create a function to build HTML searchable tables

my_data_table <- function(df){
  datatable(
    df, rownames=FALSE,
    autoHideNavigation = TRUE,
    extensions = c("Scroller",  "Buttons"),
    options = list(
      dom = 'Bfrtip',
      deferRender=TRUE,
      scrollX=TRUE, scrollY=400,
      scrollCollapse=TRUE,
      buttons =
        list('pageLength', 'colvis', 'csv', list(
          extend = 'pdf',
          pageSize = 'A4',
          orientation = 'landscape',
          filename = 'fitness_data')),
      pageLength = 692
    )
  )
}


my_data_table(fitness_data %>% select(-Comment))

Column explanations

Fitness_vial_ID: a unique identifier for each trial of the fitness assay.

Block: the experiment was run in three distinct blocks, using flies from separate generations.

Population: we measured the fitness of flies from 12 independent populations that contained autosomes that had undergone experimental evolution.

Evolutionary_treatment: the populations carried autosomes that had been exposed to one of three evolutionary conditions for 20 generations: a female-limited response to selection, a male-limited response and a control condition where the evolutionary response was unconstrained.

GFP: the GFP marker carried by the population. UBI indicates the presence of a transgene that encodes ubiquitous expression of GFP, while 3xP indicates the presence of a different transgene that encodes the expression of GFP in the ocelli.

Sex: the sex of the individuals that we were measuring the fitness of.

Rearing_vial: the vial the treatment flies used in the trial developed in. This variable is included to capture variation explained by the rearing environment e.g. small differences in food moisture content or quantity. Note that females and males can have the same rearing vial as the sexes were reared together.

Red_female_offspring: the number of adult female offspring sired/produced by flies sourced from one of the 12 populations.

Red_male_offspring: the number of adult male offspring sired/produced by flies sourced from one of the 12 populations.

bw_female_offspring: the number of adult female offspring sired/produced by the competitor flies in our fitness assay. bw is a recessive allele that encodes brown eye colour.

bw_male_offspring: the number of adult male offspring sired/produced by the competitor flies in our fitness assay. bw is a recessive allele that encodes brown eye colour.

Total_red_offspring: the total number (sexes pooled) of adult offspring sired/produced by flies sourced from one of the 12 populations.

Total_bw_offspring: the total number (sexes pooled) of adult offspring sired/produced by competitor flies.

Total_offspring: the total number (sexes and eye colours pooled) of adult offspring counted in each vial.

\(~\)

Modelling approach

\(~\)

Female and male fitness are fundamentally different concepts / traits. There are also several differences between our female and male fitness assays. The major difference is that the male assay contains half the number of females in any given vial than does the female assay. The logic behind this design choice is that sexually selected processes are a more important determinant of male fitness than they are female fitness, so any fitness differences may only be observed when competition for fertilisations is high.

For these reasons, we choose to split the data up and model female and male fitness separately.

female_fitness <- 
  fitness_data %>%
  filter(Sex == "Female")

male_fitness <- 
  fitness_data %>%
  filter(Sex == "Male") %>% 
  mutate(prop_red = Total_red_offspring / Total_offspring)

We fit the following fixed and random effects to model female and male fitness. Our aim is to estimate the causal effect that evolutionary treatment has on fitness.

Fixed effects

Block: fitness might differ between the three distinct blocks we split our experiment up into. Blocks differed temporally, used flies from different generations and different batches of food. It is also possible that there were minor fluctuations in the lighting and temperature environment experienced during development between blocks. Each of these variables may introduce variation into our fitness measurements, that can be accounted for by including the Block variable in our model.

GFP: it is possible that fitness may be affected by the GFP transgene carried by each population. For example, one could imagine that any unintended fitness effects of a transgene might be of greater magnitude if it is expressed in a larger proportion of tissues, as is the case for the UBI transgene versus the 3xP transgene. Note that each GFP type is carried by an equal number of populations from each of the three evolutionary treatments.

Evolutionary_treatment: this is the inheritance regime that the autosomes carried by each of the populations were subject to for 20 generations. There are three levels: populations carrying female-adapted autosomes, populations containing male-adapted autosomes and populations carrying control autosomes that experienced an unmanipulated inheritance regime. We are designing our model to test for a causal effect of this variable.

Random effects

Rearing_vial: the vial individual flies developed within may introduce further variation into our response variable. Like Block this variable controls for micro-environmental variation.

Population: our design contained 12 independent populations of autosomes that originated from a single outbred laboratory fly population. The populations were split and autosomes from each were subjected to one of the three evolution treatments for 20 generations. 4 populations experienced a female-limited inheritance regime, 4 a male-limited regime and 4 an unlimited or control regime.

\(~\)

Female fitness

\(~\)

To estimate the fitness of females carrying each of the three autosome types, we placed three experimental females into a yeasted vial with three female competitors that carried the bw mutation. We then introduced six males that also carried the bw mutation. We allowed them to mate and oviposit for three days, then removed all adults from the vial. 12 days later we counted all of the adult progeny in the vial and scored them for eye-colour. Progeny with red eyes were produced by the experimental females ( bw is recessive) and progeny with brown eyes were produced by the competitor females. We calculated fitness as the proportion of red eyed offspring in the vial.

\(~\)

Modelling

female_fitness.01 <-
  brm(Total_red_offspring | trials(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1|Population) + (1|Rearing_vial),
      data = female_fitness, family = binomial(), 
      prior = c(prior(normal(0, 1.5), class = Intercept),
                prior(normal(0, 2), class = b),
                prior(exponential(1), class = sd)),
      iter = 10000, warmup = 8000, chains = 4, cores = 4,
      control = list(adapt_delta = 0.999, max_treedepth = 15),
      seed = 2, file = "Fits/female_fitness.01")

print(female_fitness.01)
##  Family: binomial 
##   Links: mu = logit 
## Formula: Total_red_offspring | trials(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1 | Population) + (1 | Rearing_vial) 
##    Data: female_fitness (Number of observations: 327) 
##   Draws: 4 chains, each with iter = 10000; warmup = 8000; thin = 1;
##          total post-warmup draws = 8000
## 
## Group-Level Effects: 
## ~Population (Number of levels: 12) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.18 1.01     1090     2583
## 
## ~Rearing_vial (Number of levels: 70) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.27      0.03     0.22     0.33 1.00     2030     3600
## 
## Population-Level Effects: 
##                                      Estimate Est.Error l-95% CI u-95% CI Rhat
## Intercept                                1.09      0.09     0.91     1.27 1.00
## Evolutionary_treatmentFemale_limited     0.20      0.10    -0.00     0.40 1.00
## Evolutionary_treatmentMale_limited       0.16      0.10    -0.02     0.36 1.00
## GFPUBI                                  -0.32      0.08    -0.48    -0.16 1.00
## Block2                                  -0.58      0.08    -0.75    -0.42 1.00
## Block3                                  -0.61      0.08    -0.77    -0.45 1.00
##                                      Bulk_ESS Tail_ESS
## Intercept                                2314     3772
## Evolutionary_treatmentFemale_limited     2500     3041
## Evolutionary_treatmentMale_limited       2884     3849
## GFPUBI                                   2625     3724
## Block2                                   2042     2928
## Block3                                   1996     2892
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).

Lets see if we have any points that have a strong influence on the posterior distribution

#female_fitness.01 <- add_criterion(female_fitness.01, criterion = "loo", file = "fits/female_fitness.01")

#female_fitness.01 <- add_criterion(female_fitness.01, criterion = "waic", file = "fits/female_fitness.01")

loo(female_fitness.01)
## 
## Computed from 8000 by 327 log-likelihood matrix
## 
##          Estimate    SE
## elpd_loo  -1913.3  73.7
## p_loo       302.7  23.3
## looic      3826.6 147.4
## ------
## Monte Carlo SE of elpd_loo is NA.
## 
## Pareto k diagnostic values:
##                          Count Pct.    Min. n_eff
## (-Inf, 0.5]   (good)     241   73.7%   565       
##  (0.5, 0.7]   (ok)        53   16.2%   138       
##    (0.7, 1]   (bad)       26    8.0%   13        
##    (1, Inf)   (very bad)   7    2.1%   3         
## See help('pareto-k-diagnostic') for details.

There appear to be many points that are highly influential on the posterior. Why? It appears that this is explained by small sample sizes for some of the rearing vials. For example, female flies reared in vial 24 are only used in a single fitness assay, making estimation for this vial very difficult. It also means that the single observation for that vial has a huge effect on its posterior distribution, which returns a very high pareto k value.

There are several ways to limit the influence of these ‘outliers’ on the posterior. The first is to remove Rearing_vial from the model. While not run here, this reduces the number of highly influential points to 0. Alternatively, we can specify a different distribution family that is better equipped to deal with extreme values at the tails. This allows us to account for the potentially important variation coded by Rearing_vial. A more flexible version of the binomial is the betabinomial.

However, the beta-binomial is not a native family in brms, we need to create the distribution family using the custom_family() function. The code below is taken directly from the brms_customfamilies vignette, which can be viewed here.

beta_binomial2 <- custom_family(
  "beta_binomial2", dpars = c("mu", "phi"),
  links = c("logit", "log"), lb = c(NA, 0),
  type = "int", vars = "vint1[n]"
)


stan_funs <- "
  real beta_binomial2_lpmf(int y, real mu, real phi, int T) {
    return beta_binomial_lpmf(y | T, mu * phi, (1 - mu) * phi);
  }
  int beta_binomial2_rng(real mu, real phi, int T) {
    return beta_binomial_rng(T, mu * phi, (1 - mu) * phi);
  }
"

stanvars <- stanvar(scode = stan_funs, block = "functions")

Below we fit the same model, but this time specify a beta-binomial distribution.

female_fitness.02 <-
  brm(Total_red_offspring | vint(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1|Population) + (1|Rearing_vial),
      data = female_fitness, family = beta_binomial2, 
      prior = c(prior(normal(0, 1.5), class = Intercept),
                prior(normal(0, 2), class = b),
                prior(exponential(1), class = sd)),
      iter = 10000, warmup = 8000, chains = 4, cores = 4,
      control = list(adapt_delta = 0.95, max_treedepth = 10),
      seed = 2, stanvars = stanvars, file = "Fits/female_fitness.02")

print(female_fitness.02)
##  Family: beta_binomial2 
##   Links: mu = logit; phi = identity 
## Formula: Total_red_offspring | vint(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1 | Population) + (1 | Rearing_vial) 
##    Data: female_fitness (Number of observations: 327) 
##   Draws: 4 chains, each with iter = 10000; warmup = 8000; thin = 1;
##          total post-warmup draws = 8000
## 
## Group-Level Effects: 
## ~Population (Number of levels: 12) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.05     0.00     0.20 1.00     1658     2882
## 
## ~Rearing_vial (Number of levels: 70) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.17      0.04     0.09     0.25 1.00     2319     3274
## 
## Population-Level Effects: 
##                                      Estimate Est.Error l-95% CI u-95% CI Rhat
## Intercept                                1.13      0.09     0.94     1.31 1.00
## Evolutionary_treatmentFemale_limited     0.17      0.10    -0.02     0.37 1.00
## Evolutionary_treatmentMale_limited       0.18      0.10    -0.01     0.38 1.00
## GFPUBI                                  -0.33      0.08    -0.49    -0.16 1.00
## Block2                                  -0.64      0.08    -0.79    -0.48 1.00
## Block3                                  -0.63      0.07    -0.78    -0.49 1.00
##                                      Bulk_ESS Tail_ESS
## Intercept                                4700     5092
## Evolutionary_treatmentFemale_limited     4537     5200
## Evolutionary_treatmentMale_limited       4465     4696
## GFPUBI                                   4853     5113
## Block2                                   5339     5608
## Block3                                   4865     5524
## 
## Family Specific Parameters: 
##     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## phi    33.64      3.60    27.06    41.11 1.00     6092     5523
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
#female_fitness.02 <- add_criterion(female_fitness.02, criterion = "loo", file = "fits/female_fitness.02")

#female_fitness.02 <- add_criterion(female_fitness.02, criterion = "waic", file = "fits/female_fitness.02")

We need to write some additional code to get some post processing stuff i.e. LOO to work. Code courtesy of the brms_customfamilies vignette, which can be viewed here.

# we need to write some additional code to get some post-processing stuff to work

expose_functions(female_fitness.02, vectorize = TRUE)


log_lik_beta_binomial2 <- function(i, prep) {
  mu <- brms::get_dpar(prep, "mu", i = i)
  phi <- brms::get_dpar(prep, "phi", i = i)
  trials <- prep$data$vint1[i]
  y <- prep$data$Y[i]
  beta_binomial2_lpmf(y, mu, phi, trials)
}

posterior_predict_beta_binomial2 <- function(i, prep, ...) {
  mu <- brms::get_dpar(prep, "mu", i = i)
  phi <- brms::get_dpar(prep, "phi", i = i)
  trials <- prep$data$vint1[i]
  beta_binomial2_rng(mu, phi, trials)
}

posterior_epred_beta_binomial2 <- function(prep) {
  mu <- brms::get_dpar(prep, "mu")
  trials <- prep$data$vint1
  trials <- matrix(trials, nrow = nrow(mu), ncol = ncol(mu), byrow = TRUE)
  mu * trials
}

Run LOO to see if we’ve handled the influential points and then rank models with the loo_compare() function.

loo(female_fitness.02)
## 
## Computed from 8000 by 327 log-likelihood matrix
## 
##          Estimate   SE
## elpd_loo  -1395.5 13.0
## p_loo        36.8  3.3
## looic      2791.0 26.0
## ------
## Monte Carlo SE of elpd_loo is 0.1.
## 
## Pareto k diagnostic values:
##                          Count Pct.    Min. n_eff
## (-Inf, 0.5]   (good)     326   99.7%   1299      
##  (0.5, 0.7]   (ok)         1    0.3%   521       
##    (0.7, 1]   (bad)        0    0.0%   <NA>      
##    (1, Inf)   (very bad)   0    0.0%   <NA>      
## 
## All Pareto k estimates are ok (k < 0.7).
## See help('pareto-k-diagnostic') for details.
loo_compare(female_fitness.01, female_fitness.02, criterion = "waic")
##                   elpd_diff se_diff
## female_fitness.02    0.0       0.0 
## female_fitness.01 -505.8      62.7

The beta-binomial model looks good. It fixes our influential points problem and is preferred by the LOO metric.

Conduct a posterior predictive check to confirm our model is doing what we want it to.

pp_check(female_fitness.02, type = "hist", ndraws = 11, binwidth = 10) +
  theme_minimal() +
  theme(panel.background = element_blank())

The posterior predictive distribution matches our raw data quite well, indicating the model is functioning as we wanted.

\(~\)

Derive predictions from the posterior

Get predictions from the model and present them in a Table

draws <- as_draws_df(female_fitness.02)

draws_female <-
  draws  %>% 
  mutate(`Female-limited` = inv_logit_scaled(b_Intercept + b_Evolutionary_treatmentFemale_limited),
         `Male-limited` = inv_logit_scaled(b_Intercept + b_Evolutionary_treatmentMale_limited),
         Control = inv_logit_scaled(b_Intercept)) %>% 
  select(Control, `Female-limited`, `Male-limited`) %>% 
    pivot_longer(cols = c(Control, `Female-limited`, `Male-limited`),
                 names_to = "Evolutionary_treatment") %>% 
  rename(prop_focal_offspring = value) %>% 
  arrange(Evolutionary_treatment)

draws_female %>% 
  group_by(Evolutionary_treatment) %>% 
  summarise(`Estimated prop. of offspring produced` = median(prop_focal_offspring),
            `2.5%` = quantile(prop_focal_offspring, probs = 0.025),
            `97.5%` = quantile(prop_focal_offspring, probs = 0.975)) %>% 
  rename(`Inheritance treatment` = Evolutionary_treatment) %>% 
  pander(split.cell = 40, split.table = Inf, round = 3)
Inheritance treatment Estimated prop. of offspring produced 2.5% 97.5%
Control 0.755 0.719 0.787
Female-limited 0.786 0.751 0.816
Male-limited 0.788 0.754 0.817
# now find the differences between the control and the sex-limited treatments

# the inv_logit_scaled() function converts the posterior draws onto the response scale 

  draws %>% 
  mutate(p_control =  inv_logit_scaled(b_Intercept),
         p_female = inv_logit_scaled(b_Evolutionary_treatmentFemale_limited + b_Intercept),
         p_male = inv_logit_scaled(b_Evolutionary_treatmentMale_limited + b_Intercept),
         `Female-limited` = p_female / p_control,
         `Male-limited` = p_male / p_control) %>% 
  gather(key = `difference comparison`, value = `% difference`) %>% 
  filter(`difference comparison` == c("Female-limited", "Male-limited")) %>% 
  group_by(`difference comparison`)  %>% 
  summarise(`Mean proportion of offspring produced relative to control`  = mean(`% difference`),
            `2.5%` = quantile(`% difference`, probs = 0.025),
            `97.5%` = quantile(`% difference`, probs = 0.975)) %>% 
  rename(`Inheritance treatment` = `difference comparison`) %>% 
  pander(split.cell = 40, split.table = Inf, round = 3)
Inheritance treatment Mean proportion of offspring produced relative to control 2.5% 97.5%
Female-limited 1.041 0.995 1.089
Male-limited 1.043 0.997 1.092

\(~\)

Male fitness

\(~\)

To estimate the fitness of males carrying each of the three chromosome types, we conducted an experiment very similar to the female fitness assay. However, because male fitness has stronger covariance with fertilisation events than does female fitness, we conducted the male fitness assay with a 1:2 sex ratio (female:male) rather than the 1:1 ratio used in the female assay. This increases the strength of sexual selection and is a more appopriate way to expose differences in fitness between groups of males. As with the females, we calculated fitness as the proportion of red eyed offspring in the vial.

Alternative modelling approaches

Binomial model with rearing vial

male_fitness.01 <-
  brm(Total_red_offspring | trials(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1|Population) + (1|Rearing_vial),
      data = male_fitness, family = binomial(), 
      prior = c(prior(normal(0, 1.5), class = Intercept),
                prior(normal(0, 2), class = b),
                prior(exponential(1), class = sd)),
      iter = 10000, warmup = 8000, chains = 4, cores = 4,
      control = list(adapt_delta = 0.999, max_treedepth = 15),
      seed = 2, file = "Fits/male_fitness.01")


print(male_fitness.01)
##  Family: binomial 
##   Links: mu = logit 
## Formula: Total_red_offspring | trials(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1 | Population) + (1 | Rearing_vial) 
##    Data: male_fitness (Number of observations: 360) 
##   Draws: 4 chains, each with iter = 10000; warmup = 8000; thin = 1;
##          total post-warmup draws = 8000
## 
## Group-Level Effects: 
## ~Population (Number of levels: 12) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.30      0.15     0.06     0.64 1.00     1307     2009
## 
## ~Rearing_vial (Number of levels: 72) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.61      0.06     0.50     0.75 1.00     2567     4428
## 
## Population-Level Effects: 
##                                      Estimate Est.Error l-95% CI u-95% CI Rhat
## Intercept                                0.66      0.26     0.13     1.18 1.00
## Evolutionary_treatmentFemale_limited     0.13      0.29    -0.44     0.73 1.00
## Evolutionary_treatmentMale_limited       0.27      0.30    -0.34     0.86 1.00
## GFPUBI                                  -0.08      0.23    -0.57     0.35 1.00
## Block2                                   0.92      0.18     0.56     1.28 1.00
## Block3                                   0.05      0.18    -0.30     0.40 1.00
##                                      Bulk_ESS Tail_ESS
## Intercept                                5006     4605
## Evolutionary_treatmentFemale_limited     5510     4532
## Evolutionary_treatmentMale_limited       5350     4628
## GFPUBI                                   5054     5100
## Block2                                   3643     4695
## Block3                                   3626     4385
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).

Like with the female fitness model, lets see if we have any points that have a strong influence on the posterior distribution. Run LOO:

#male_fitness.01 <- add_criterion(male_fitness.04, criterion = "loo", file = "fits/male_fitness.04")
#male_fitness.01 <- add_criterion(male_fitness.01, criterion = "waic", file = "fits/male_fitness.01")

loo(male_fitness.01)
## 
## Computed from 8000 by 360 log-likelihood matrix
## 
##          Estimate    SE
## elpd_loo  -5494.1 310.1
## p_loo      1393.9 101.3
## looic     10988.2 620.3
## ------
## Monte Carlo SE of elpd_loo is NA.
## 
## Pareto k diagnostic values:
##                          Count Pct.    Min. n_eff
## (-Inf, 0.5]   (good)     141   39.2%   218       
##  (0.5, 0.7]   (ok)        75   20.8%   66        
##    (0.7, 1]   (bad)       65   18.1%   15        
##    (1, Inf)   (very bad)  79   21.9%   1         
## See help('pareto-k-diagnostic') for details.

Conduct the posterior predictive check…

pp_check(male_fitness.01, type = "hist", ndraws = 11, binwidth = 10) +
  theme_minimal() +
  theme(panel.background = element_blank())

Binomial model without rearing vial

Like with the female model, there appears to be many points that are highly influential on the posterior. I remove Rearing_vial once more to see if this is the variable responsible for making certain points highly influential.

male_fitness.02 <-
  brm(Total_red_offspring | trials(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1|Population),
      data = male_fitness, family = binomial(), 
      prior = c(prior(normal(0, 1.5), class = Intercept),
                prior(normal(0, 2), class = b),
                prior(exponential(1), class = sd)),
      iter = 4000, warmup = 2000, chains = 4, cores = 4,
      control = list(adapt_delta = 0.8, max_treedepth = 10),
      seed = 2, file = "Fits/male_fitness.02")

Run LOO

#male_fitness.02 <- add_criterion(male_fitness.02, criterion = "loo", file = "fits/male_fitness.02")

#male_fitness.02 <- add_criterion(male_fitness.02, criterion = "waic", file = "fits/male_fitness.02")

loo(male_fitness.02)
## 
## Computed from 8000 by 360 log-likelihood matrix
## 
##          Estimate    SE
## elpd_loo  -5624.8 304.2
## p_loo       347.0  27.0
## looic     11249.5 608.4
## ------
## Monte Carlo SE of elpd_loo is NA.
## 
## Pareto k diagnostic values:
##                          Count Pct.    Min. n_eff
## (-Inf, 0.5]   (good)     316   87.8%   372       
##  (0.5, 0.7]   (ok)        27    7.5%   124       
##    (0.7, 1]   (bad)       15    4.2%   25        
##    (1, Inf)   (very bad)   2    0.6%   13        
## See help('pareto-k-diagnostic') for details.

Conduct the posterior predictive check…

pp_check(male_fitness.02, type = "hist", ndraws = 11, binwidth = 10) +
  theme_minimal() +
  theme(panel.background = element_blank())

Removing Rearing_vial reduces the number of highly influential points, however this time 14 remain…

Beta-binomial model

male_fitness.03 <-
  brm(Total_red_offspring | vint(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1|Population) + (1|Rearing_vial),
      data = male_fitness, family = beta_binomial2, 
      prior = c(prior(normal(0, 1.5), class = Intercept),
                prior(normal(0, 2), class = b),
                prior(exponential(1), class = sd)),
      iter = 10000, warmup = 8000, chains = 4, cores = 4,
      stanvars = stanvars,
      control = list(adapt_delta = 0.9, max_treedepth = 10),
      seed = 2, file = "Fits/male_fitness.03")

print(male_fitness.03)
##  Family: beta_binomial2 
##   Links: mu = logit; phi = identity 
## Formula: Total_red_offspring | vint(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1 | Population) + (1 | Rearing_vial) 
##    Data: male_fitness (Number of observations: 360) 
##   Draws: 4 chains, each with iter = 10000; warmup = 8000; thin = 1;
##          total post-warmup draws = 8000
## 
## Group-Level Effects: 
## ~Population (Number of levels: 12) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.29      0.13     0.06     0.60 1.00     2214     2085
## 
## ~Rearing_vial (Number of levels: 72) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.16      0.10     0.01     0.38 1.00     2143     3826
## 
## Population-Level Effects: 
##                                      Estimate Est.Error l-95% CI u-95% CI Rhat
## Intercept                                0.77      0.23     0.31     1.22 1.00
## Evolutionary_treatmentFemale_limited     0.42      0.27    -0.11     0.95 1.00
## Evolutionary_treatmentMale_limited       0.10      0.26    -0.42     0.63 1.00
## GFPUBI                                  -0.34      0.22    -0.78     0.10 1.00
## Block2                                   0.98      0.15     0.69     1.28 1.00
## Block3                                  -0.03      0.14    -0.30     0.25 1.00
##                                      Bulk_ESS Tail_ESS
## Intercept                                5593     5203
## Evolutionary_treatmentFemale_limited     5048     4596
## Evolutionary_treatmentMale_limited       5141     5227
## GFPUBI                                   5347     4793
## Block2                                   9012     5026
## Block3                                   9113     5995
## 
## Family Specific Parameters: 
##     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## phi     3.65      0.31     3.08     4.29 1.00    10770     5671
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).

Quick bit of code to get our custom family post-processing to work

expose_functions(male_fitness.03, vectorize = TRUE)

Run LOO

#male_fitness.03 <- add_criterion(male_fitness.03, criterion = "loo", file = "fits/male_fitness.03")

#male_fitness.03 <- add_criterion(male_fitness.03, criterion = "waic", file = "fits/male_fitness.03")

loo(male_fitness.03)
## 
## Computed from 8000 by 360 log-likelihood matrix
## 
##          Estimate   SE
## elpd_loo  -1561.9 21.4
## p_loo        23.2  1.9
## looic      3123.7 42.9
## ------
## Monte Carlo SE of elpd_loo is NA.
## 
## Pareto k diagnostic values:
##                          Count Pct.    Min. n_eff
## (-Inf, 0.5]   (good)     358   99.4%   2421      
##  (0.5, 0.7]   (ok)         1    0.3%   2668      
##    (0.7, 1]   (bad)        0    0.0%   <NA>      
##    (1, Inf)   (very bad)   1    0.3%   4000      
## See help('pareto-k-diagnostic') for details.
loo_compare(male_fitness.01, male_fitness.02, male_fitness.03, criterion = "loo")
##                 elpd_diff se_diff
## male_fitness.03     0.0       0.0
## male_fitness.01 -3932.2     305.5
## male_fitness.02 -4062.9     298.9

There is only a single point now that LOO is worried about, even while including Rearing_vial as a random effect. The beta-binomial model also performs the best by the LOO and WAIC metrics.

Conduct the posterior predictive check…

pp_check(male_fitness.03, type = "hist", ndraws = 11, binwidth = 10) +
  theme_minimal() +
  theme(panel.background = element_blank())

Zero-one-inflated beta

Another interesting aspect to these data are the prevalence of 1 values. That is, there are many trials where the red-eyed males carrying the experimentally evolved autosomes sire all of the offspring produced in the vial. These extreme values are not handled well by binomial models. Instead we can model the proportion of red-eyed offspring using a zero-one-inflated beta model.

male_fitness.04 <-
  brm(prop_red ~ 1 + Evolutionary_treatment + GFP + Block + (1|Population) + (1|Rearing_vial),
      data = male_fitness, family = zero_one_inflated_beta(), 
      prior = c(prior(normal(0, 1.5), class = Intercept),
                prior(normal(0, 2), class = b),
                prior(exponential(1), class = sd)),
      iter = 10000, warmup = 8000, chains = 4, cores = 4,
      control = list(adapt_delta = 0.999, max_treedepth = 15),
      seed = 2, file = "Fits/male_fitness.04")


print(male_fitness.01)
##  Family: binomial 
##   Links: mu = logit 
## Formula: Total_red_offspring | trials(Total_offspring) ~ 1 + Evolutionary_treatment + GFP + Block + (1 | Population) + (1 | Rearing_vial) 
##    Data: male_fitness (Number of observations: 360) 
##   Draws: 4 chains, each with iter = 10000; warmup = 8000; thin = 1;
##          total post-warmup draws = 8000
## 
## Group-Level Effects: 
## ~Population (Number of levels: 12) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.30      0.15     0.06     0.64 1.00     1307     2009
## 
## ~Rearing_vial (Number of levels: 72) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.61      0.06     0.50     0.75 1.00     2567     4428
## 
## Population-Level Effects: 
##                                      Estimate Est.Error l-95% CI u-95% CI Rhat
## Intercept                                0.66      0.26     0.13     1.18 1.00
## Evolutionary_treatmentFemale_limited     0.13      0.29    -0.44     0.73 1.00
## Evolutionary_treatmentMale_limited       0.27      0.30    -0.34     0.86 1.00
## GFPUBI                                  -0.08      0.23    -0.57     0.35 1.00
## Block2                                   0.92      0.18     0.56     1.28 1.00
## Block3                                   0.05      0.18    -0.30     0.40 1.00
##                                      Bulk_ESS Tail_ESS
## Intercept                                5006     4605
## Evolutionary_treatmentFemale_limited     5510     4532
## Evolutionary_treatmentMale_limited       5350     4628
## GFPUBI                                   5054     5100
## Block2                                   3643     4695
## Block3                                   3626     4385
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
#male_fitness.04 <- add_criterion(male_fitness.04, criterion = "loo", file = "fits/male_fitness.04")
#male_fitness.01 <- add_criterion(male_fitness.01, criterion = "waic", file = "fits/male_fitness.01")

loo(male_fitness.04)
## 
## Computed from 8000 by 359 log-likelihood matrix
## 
##          Estimate   SE
## elpd_loo    -28.7 17.9
## p_loo        16.7  1.4
## looic        57.4 35.9
## ------
## Monte Carlo SE of elpd_loo is 0.0.
## 
## All Pareto k estimates are good (k < 0.5).
## See help('pareto-k-diagnostic') for details.

Note that we no longer have any values with high influence.

Conduct the posterior predictive check…

pp_check(male_fitness.04, type = "hist", ndraws = 11, binwidth = 0.1) +
  theme_minimal() +
  theme(panel.background = element_blank())

Derive estimates from posterior

Get predictions from the model and present them in a Table

draws_m <- as_draws_df(male_fitness.03)

draws_male <-
  draws_m  %>% 
  mutate(`Female-limited` = inv_logit_scaled(b_Intercept + b_Evolutionary_treatmentFemale_limited),
         `Male-limited` = inv_logit_scaled(b_Intercept + b_Evolutionary_treatmentMale_limited),
         Control = inv_logit_scaled(b_Intercept)) %>% 
  select(Control, `Female-limited`, `Male-limited`) %>% 
    pivot_longer(cols = c(Control, `Female-limited`, `Male-limited`),
                 names_to = "Evolutionary_treatment") %>% 
  rename(prop_focal_offspring = value)

draws_male %>% 
  group_by(Evolutionary_treatment) %>% 
  summarise(`Estimated prop. of offspring sired` = median(prop_focal_offspring),
            `2.5%` = quantile(prop_focal_offspring, probs = 0.025),
            `97.5%` = quantile(prop_focal_offspring, probs = 0.975)) %>% 
  rename(`Inheritance treatment` = Evolutionary_treatment) %>% 
  pander(split.cell = 40, split.table = Inf, round = 3)
Inheritance treatment Estimated prop. of offspring sired 2.5% 97.5%
Control 0.684 0.577 0.772
Female-limited 0.768 0.674 0.838
Male-limited 0.707 0.604 0.792
# now find the differences between the control and the sex-limited Evolution_treatments

# the inv_logit_scaled() function converts the posterior draws onto the response scale 

draws_m %>% 
  mutate(p_control =  inv_logit_scaled(b_Intercept),
         p_female = inv_logit_scaled(b_Evolutionary_treatmentFemale_limited + b_Intercept),
         p_male = inv_logit_scaled(b_Evolutionary_treatmentMale_limited + b_Intercept),
         `Female-limited` = p_female / p_control,
         `Male-limited` = p_male / p_control) %>% 
  gather(key = `difference comparison`, value = `% difference`) %>% 
  filter(`difference comparison` == c("Female-limited", "Male-limited")) %>% 
  group_by(`difference comparison`)  %>% 
  summarise(`Mean proportion of offspring sired relative to control`  = mean(`% difference`),
            `2.5%` = quantile(`% difference`, probs = 0.025),
            `97.5%` = quantile(`% difference`, probs = 0.975)) %>% 
  rename(`Inheritance treatment` = `difference comparison`) %>% 
  pander(split.cell = 40, split.table = Inf, round = 3)
Inheritance treatment Mean proportion of offspring sired relative to control 2.5% 97.5%
Female-limited 1.126 0.966 1.323
Male-limited 1.035 0.878 1.214

Building Figure 1

# female plots

f_1 <-
  draws_female %>% 
  ggplot(aes(Evolutionary_treatment, prop_focal_offspring)) + 
  stat_eye(aes(fill = Evolutionary_treatment), .width = c(0.66, 0.95), alpha = 1) + # width indicates the uncertainty intervals: here we have 66% and 95% intervals
  scale_fill_manual(values = met.brewer("Hiroshige", 3)) +
  scale_y_continuous("Female fitness\n(proportion of offspring produced)",
                     breaks = c(0.7, 0.8)) +
  #coord_cartesian(ylim = c(0.4, 1)) +
  xlab(NULL) +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank())

f_2 <-
  draws %>% 
  mutate(`Female-limited` = b_Evolutionary_treatmentFemale_limited,
         `Male-limited` = b_Evolutionary_treatmentMale_limited) %>% 
  gather(key = parameter, value = logodds) %>% 
  filter(parameter == c("Female-limited", "Male-limited")) %>%
  as_tibble() %>% 
  
  ggplot(aes(parameter, logodds)) + 
  stat_halfeye(aes(fill = parameter), .width = c(0.66, 0.95)) + # width indicates the uncertainty intervals: here we have 66% and 95% intervals
  scale_fill_manual(values = c("Female-limited" = "#ffd06f", "Male-limited" = "#72bcd5")) + 
  coord_flip() +
  geom_hline(yintercept = 0, linetype = 2) +
  scale_y_continuous(breaks = c(-1, 0, 1)) +
  xlab(NULL) +
  ylab(NULL) +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank())

# male plots

f_3 <-
  draws_male %>% 
  ggplot(aes(Evolutionary_treatment, prop_focal_offspring)) + 
  stat_eye(aes(fill = Evolutionary_treatment), .width = c(0.66, 0.95), alpha = 1) + # width indicates the uncertainty intervals: here we have 66% and 95% intervals
  scale_fill_manual(values = met.brewer("Hiroshige", 3)) +
  scale_y_continuous("Male fitness\n(proportion of offspring sired)",
                     breaks = c(0.4, 0.6, 0.8)) +
  #coord_cartesian(ylim = c(0.4, 1)) +
  xlab("Inheritance treatment") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank())

f_4 <-
  draws_m %>% 
  mutate(`Female-limited` = b_Evolutionary_treatmentFemale_limited,
         `Male-limited` = b_Evolutionary_treatmentMale_limited) %>% 
  gather(key = parameter, value = logodds) %>% 
  filter(parameter == c("Female-limited", "Male-limited")) %>%
  as_tibble() %>% 
  #mutate(parameter =factor(parameter, levels=c("SD-Mad", "SD-72", "SD-5"))) %>%
  
  ggplot(aes(parameter, logodds)) + 
  stat_halfeye(aes(fill = parameter), .width = c(0.66, 0.95)) + # width indicates the uncertainty intervals: here we have 66% and 95% intervals
  scale_fill_manual(values = c("Female-limited" = "#ffd06f", "Male-limited" = "#72bcd5")) + 
  coord_flip(ylim = c(-1, 1)) +
  geom_hline(yintercept = 0, linetype = 2) +
  scale_y_continuous(breaks = c(-1, 0, 1)) +
  xlab(NULL) +
  ylab("Log-odds mean difference from control") +
  theme_bw() + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank())


(f_1 + f_2) /(f_3 + f_4)

Figure 1: a shows the estimated mean female fitness for flies carrying autosomes that had previously experienced unconstrained inheritance (control), female-limited inheritance or male-limited inheritance. b shows the log-odds mean difference in means between the sex-limited treatments and the control evolutionary treatment. c and d depict the same things as a and b, except for estimated mean male fitness.

LS0tDQp0aXRsZTogIkV4cGVyaW1lbnRhbCBlbmZvcmNlbWVudCBvZiBzZXgtbGltaXRlZCBhZGFwdGF0aW9uIg0KYXV0aG9yOiAiVGhvbWFzIEtlYW5leSwgSGVpZGkgV29uZywgVGhlcmVzYSBKb25lcyBhbmQgTHVrZSBIb2xtYW4iDQojYmlibGlvZ3JhcGh5OiAic3VwcF9yZWZlcmVuY2VzLmJpYiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBkZXB0aDogMQ0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0aGVtZTogeWV0aQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQplZGl0b3Jfb3B0aW9uczoNCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQoNCg0KYGBge3J9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBjYWNoZSA9IFRSVUUpDQpgYGANCg0KIyBTZXR1cCBmb3IgYW5hbHlzaXMNCg0KIyMgTG9hZCBwYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKSAjIHRpZHkgc3R5bGUgY29kaW5nDQpsaWJyYXJ5KGJybXMpICMgQmF5ZXNpYW4gbW9kZWxzDQpsaWJyYXJ5KGxvbykgIyB0byB1c2UgaW5mb3JtYXRpb24gY3JpdGVyaWEgaW4gYnJtcyBtb2RlbHMNCmxpYnJhcnkodGlkeWJheWVzKSAjIEJheWVzaWFuIGFlc3RoZXRpY3MNCmxpYnJhcnkoTWV0QnJld2VyKSAjIGNvbG91cnMNCmxpYnJhcnkoa2FibGVFeHRyYSkgIyB0YWJsZXMNCmxpYnJhcnkocGF0Y2h3b3JrKSAjIHB1dHRpbmcgcGxvdHMgdG9nZXRoZXINCmxpYnJhcnkoRFQpICMgZm9yIHNlYXJjaC0gYW5kIHNhdmVhYmxlIHRhYmxlcw0KbGlicmFyeShwYW5kZXIpICMgZm9yIHNpbXBsZXIgdGFibGVzDQoNCmBgYA0KDQojIyBMb2FkIGluIHRoZSBkYXRhIA0KDQokfiQNCg0KYGBge3J9DQoNCmZpdG5lc3NfZGF0YSA8LSByZWFkX2NzdigiZGF0YS9TTENfZml0bmVzc19kYXRhLmNzdiIpICU+JSANCiAgbXV0YXRlKEZpdG5lc3NfdmlhbF9JRCA9IGFzLmZhY3RvcihGaXRuZXNzX3ZpYWxfSUQpLA0KICAgICAgICAgQmxvY2sgPSBhcy5mYWN0b3IoQmxvY2spLA0KICAgICAgICAgUG9wdWxhdGlvbiA9IGFzLmZhY3RvcihQb3B1bGF0aW9uKSwNCiAgICAgICAgIFRyZWF0bWVudCA9IGFzLmZhY3RvcihUcmVhdG1lbnQpLA0KICAgICAgICAgR0ZQID0gYXMuZmFjdG9yKEdGUCksDQogICAgICAgICBTZXggPSBhcy5mYWN0b3IoU2V4KSwNCiAgICAgICAgIFJlYXJpbmdfdmlhbCA9IGFzLmZhY3RvcihSZWFyaW5nX3ZpYWwpLA0KICAgICAgICAgVG90YWxfcmVkX29mZnNwcmluZyA9IFJlZF9mZW1hbGVfb2Zmc3ByaW5nICsgUmVkX21hbGVfb2Zmc3ByaW5nLA0KICAgICAgICAgVG90YWxfYndfb2Zmc3ByaW5nID0gYndfZmVtYWxlX29mZnNwcmluZyArIGJ3X21hbGVfb2Zmc3ByaW5nLA0KICAgICAgICAgVG90YWxfb2Zmc3ByaW5nID0gVG90YWxfcmVkX29mZnNwcmluZyArIFRvdGFsX2J3X29mZnNwcmluZykgJT4lIA0KICByZW5hbWUoRXZvbHV0aW9uYXJ5X3RyZWF0bWVudCA9IFRyZWF0bWVudCkNCg0KIyBDcmVhdGUgYSBmdW5jdGlvbiB0byBidWlsZCBIVE1MIHNlYXJjaGFibGUgdGFibGVzDQoNCm15X2RhdGFfdGFibGUgPC0gZnVuY3Rpb24oZGYpew0KICBkYXRhdGFibGUoDQogICAgZGYsIHJvd25hbWVzPUZBTFNFLA0KICAgIGF1dG9IaWRlTmF2aWdhdGlvbiA9IFRSVUUsDQogICAgZXh0ZW5zaW9ucyA9IGMoIlNjcm9sbGVyIiwgICJCdXR0b25zIiksDQogICAgb3B0aW9ucyA9IGxpc3QoDQogICAgICBkb20gPSAnQmZydGlwJywNCiAgICAgIGRlZmVyUmVuZGVyPVRSVUUsDQogICAgICBzY3JvbGxYPVRSVUUsIHNjcm9sbFk9NDAwLA0KICAgICAgc2Nyb2xsQ29sbGFwc2U9VFJVRSwNCiAgICAgIGJ1dHRvbnMgPQ0KICAgICAgICBsaXN0KCdwYWdlTGVuZ3RoJywgJ2NvbHZpcycsICdjc3YnLCBsaXN0KA0KICAgICAgICAgIGV4dGVuZCA9ICdwZGYnLA0KICAgICAgICAgIHBhZ2VTaXplID0gJ0E0JywNCiAgICAgICAgICBvcmllbnRhdGlvbiA9ICdsYW5kc2NhcGUnLA0KICAgICAgICAgIGZpbGVuYW1lID0gJ2ZpdG5lc3NfZGF0YScpKSwNCiAgICAgIHBhZ2VMZW5ndGggPSA2OTINCiAgICApDQogICkNCn0NCg0KDQpteV9kYXRhX3RhYmxlKGZpdG5lc3NfZGF0YSAlPiUgc2VsZWN0KC1Db21tZW50KSkNCg0KYGBgDQoNCioqQ29sdW1uIGV4cGxhbmF0aW9ucyoqDQoNCkZpdG5lc3NfdmlhbF9JRDogYSB1bmlxdWUgaWRlbnRpZmllciBmb3IgZWFjaCB0cmlhbCBvZiB0aGUgZml0bmVzcyBhc3NheS4NCg0KQmxvY2s6IHRoZSBleHBlcmltZW50IHdhcyBydW4gaW4gdGhyZWUgZGlzdGluY3QgYmxvY2tzLCB1c2luZyBmbGllcyBmcm9tIHNlcGFyYXRlIGdlbmVyYXRpb25zLg0KDQpQb3B1bGF0aW9uOiB3ZSBtZWFzdXJlZCB0aGUgZml0bmVzcyBvZiBmbGllcyBmcm9tIDEyIGluZGVwZW5kZW50IHBvcHVsYXRpb25zIHRoYXQgY29udGFpbmVkIGF1dG9zb21lcyB0aGF0IGhhZCB1bmRlcmdvbmUgZXhwZXJpbWVudGFsIGV2b2x1dGlvbi4NCg0KRXZvbHV0aW9uYXJ5X3RyZWF0bWVudDogdGhlIHBvcHVsYXRpb25zIGNhcnJpZWQgYXV0b3NvbWVzIHRoYXQgaGFkIGJlZW4gZXhwb3NlZCB0byBvbmUgb2YgdGhyZWUgZXZvbHV0aW9uYXJ5IGNvbmRpdGlvbnMgZm9yIDIwIGdlbmVyYXRpb25zOiBhIGZlbWFsZS1saW1pdGVkIHJlc3BvbnNlIHRvIHNlbGVjdGlvbiwgYSBtYWxlLWxpbWl0ZWQgcmVzcG9uc2UgYW5kIGEgY29udHJvbCBjb25kaXRpb24gd2hlcmUgdGhlIGV2b2x1dGlvbmFyeSByZXNwb25zZSB3YXMgdW5jb25zdHJhaW5lZC4NCg0KR0ZQOiB0aGUgR0ZQIG1hcmtlciBjYXJyaWVkIGJ5IHRoZSBwb3B1bGF0aW9uLiBVQkkgaW5kaWNhdGVzIHRoZSBwcmVzZW5jZSBvZiBhIHRyYW5zZ2VuZSB0aGF0IGVuY29kZXMgdWJpcXVpdG91cyBleHByZXNzaW9uIG9mIEdGUCwgd2hpbGUgM3hQIGluZGljYXRlcyB0aGUgcHJlc2VuY2Ugb2YgYSBkaWZmZXJlbnQgdHJhbnNnZW5lIHRoYXQgZW5jb2RlcyB0aGUgZXhwcmVzc2lvbiBvZiBHRlAgaW4gdGhlIG9jZWxsaS4gDQoNClNleDogdGhlIHNleCBvZiB0aGUgaW5kaXZpZHVhbHMgdGhhdCB3ZSB3ZXJlIG1lYXN1cmluZyB0aGUgZml0bmVzcyBvZi4NCg0KUmVhcmluZ192aWFsOiB0aGUgdmlhbCB0aGUgdHJlYXRtZW50IGZsaWVzIHVzZWQgaW4gdGhlIHRyaWFsIGRldmVsb3BlZCBpbi4gVGhpcyB2YXJpYWJsZSBpcyBpbmNsdWRlZCB0byBjYXB0dXJlIHZhcmlhdGlvbiBleHBsYWluZWQgYnkgdGhlIHJlYXJpbmcgZW52aXJvbm1lbnQgZS5nLiBzbWFsbCBkaWZmZXJlbmNlcyBpbiBmb29kIG1vaXN0dXJlIGNvbnRlbnQgb3IgcXVhbnRpdHkuIE5vdGUgdGhhdCBmZW1hbGVzIGFuZCBtYWxlcyBjYW4gaGF2ZSB0aGUgc2FtZSByZWFyaW5nIHZpYWwgYXMgdGhlIHNleGVzIHdlcmUgcmVhcmVkIHRvZ2V0aGVyLg0KDQpSZWRfZmVtYWxlX29mZnNwcmluZzogdGhlIG51bWJlciBvZiBhZHVsdCBmZW1hbGUgb2Zmc3ByaW5nIHNpcmVkL3Byb2R1Y2VkIGJ5IGZsaWVzIHNvdXJjZWQgZnJvbSBvbmUgb2YgdGhlIDEyIHBvcHVsYXRpb25zLg0KDQpSZWRfbWFsZV9vZmZzcHJpbmc6IHRoZSBudW1iZXIgb2YgYWR1bHQgbWFsZSBvZmZzcHJpbmcgc2lyZWQvcHJvZHVjZWQgYnkgZmxpZXMgc291cmNlZCBmcm9tIG9uZSBvZiB0aGUgMTIgcG9wdWxhdGlvbnMuDQoNCmJ3X2ZlbWFsZV9vZmZzcHJpbmc6IHRoZSBudW1iZXIgb2YgYWR1bHQgZmVtYWxlIG9mZnNwcmluZyBzaXJlZC9wcm9kdWNlZCBieSB0aGUgY29tcGV0aXRvciBmbGllcyBpbiBvdXIgZml0bmVzcyBhc3NheS4gX2J3XyBpcyBhIHJlY2Vzc2l2ZSBhbGxlbGUgdGhhdCBlbmNvZGVzIGJyb3duIGV5ZSBjb2xvdXIuDQoNCmJ3X21hbGVfb2Zmc3ByaW5nOiB0aGUgbnVtYmVyIG9mIGFkdWx0IG1hbGUgb2Zmc3ByaW5nIHNpcmVkL3Byb2R1Y2VkIGJ5IHRoZSBjb21wZXRpdG9yIGZsaWVzIGluIG91ciBmaXRuZXNzIGFzc2F5LiBfYndfIGlzIGEgcmVjZXNzaXZlIGFsbGVsZSB0aGF0IGVuY29kZXMgYnJvd24gZXllIGNvbG91ci4NCg0KVG90YWxfcmVkX29mZnNwcmluZzogdGhlIHRvdGFsIG51bWJlciAoc2V4ZXMgcG9vbGVkKSBvZiBhZHVsdCBvZmZzcHJpbmcgc2lyZWQvcHJvZHVjZWQgYnkgZmxpZXMgc291cmNlZCBmcm9tIG9uZSBvZiB0aGUgMTIgcG9wdWxhdGlvbnMuDQoNClRvdGFsX2J3X29mZnNwcmluZzogdGhlIHRvdGFsIG51bWJlciAoc2V4ZXMgcG9vbGVkKSBvZiBhZHVsdCBvZmZzcHJpbmcgc2lyZWQvcHJvZHVjZWQgYnkgY29tcGV0aXRvciBmbGllcy4NCg0KVG90YWxfb2Zmc3ByaW5nOiB0aGUgdG90YWwgbnVtYmVyIChzZXhlcyBhbmQgZXllIGNvbG91cnMgcG9vbGVkKSBvZiBhZHVsdCBvZmZzcHJpbmcgY291bnRlZCBpbiBlYWNoIHZpYWwuDQoNCg0KJH4kDQoNCiMgTW9kZWxsaW5nIGFwcHJvYWNoDQoNCiR+JA0KDQpGZW1hbGUgYW5kIG1hbGUgZml0bmVzcyBhcmUgZnVuZGFtZW50YWxseSBkaWZmZXJlbnQgY29uY2VwdHMgLyB0cmFpdHMuIFRoZXJlIGFyZSBhbHNvIHNldmVyYWwgZGlmZmVyZW5jZXMgYmV0d2VlbiBvdXIgZmVtYWxlIGFuZCBtYWxlIGZpdG5lc3MgYXNzYXlzLiBUaGUgbWFqb3IgZGlmZmVyZW5jZSBpcyB0aGF0IHRoZSBtYWxlIGFzc2F5IGNvbnRhaW5zIGhhbGYgdGhlIG51bWJlciBvZiBmZW1hbGVzIGluIGFueSBnaXZlbiB2aWFsIHRoYW4gZG9lcyB0aGUgZmVtYWxlIGFzc2F5LiBUaGUgbG9naWMgYmVoaW5kIHRoaXMgZGVzaWduIGNob2ljZSBpcyB0aGF0IHNleHVhbGx5IHNlbGVjdGVkIHByb2Nlc3NlcyBhcmUgYSBtb3JlIGltcG9ydGFudCBkZXRlcm1pbmFudCBvZiBtYWxlIGZpdG5lc3MgdGhhbiB0aGV5IGFyZSBmZW1hbGUgZml0bmVzcywgc28gYW55IGZpdG5lc3MgZGlmZmVyZW5jZXMgbWF5IG9ubHkgYmUgb2JzZXJ2ZWQgd2hlbiBjb21wZXRpdGlvbiBmb3IgZmVydGlsaXNhdGlvbnMgaXMgaGlnaC4gDQoNCkZvciB0aGVzZSByZWFzb25zLCB3ZSBjaG9vc2UgdG8gc3BsaXQgdGhlIGRhdGEgdXAgYW5kIG1vZGVsIGZlbWFsZSBhbmQgbWFsZSBmaXRuZXNzIHNlcGFyYXRlbHkuDQoNCmBgYHtyfQ0KZmVtYWxlX2ZpdG5lc3MgPC0gDQogIGZpdG5lc3NfZGF0YSAlPiUNCiAgZmlsdGVyKFNleCA9PSAiRmVtYWxlIikNCg0KbWFsZV9maXRuZXNzIDwtIA0KICBmaXRuZXNzX2RhdGEgJT4lDQogIGZpbHRlcihTZXggPT0gIk1hbGUiKSAlPiUgDQogIG11dGF0ZShwcm9wX3JlZCA9IFRvdGFsX3JlZF9vZmZzcHJpbmcgLyBUb3RhbF9vZmZzcHJpbmcpDQogIA0KYGBgDQoNCldlIGZpdCB0aGUgZm9sbG93aW5nIGZpeGVkIGFuZCByYW5kb20gZWZmZWN0cyB0byBtb2RlbCBmZW1hbGUgYW5kIG1hbGUgZml0bmVzcy4gT3VyIGFpbSBpcyB0byBlc3RpbWF0ZSB0aGUgY2F1c2FsIGVmZmVjdCB0aGF0IGBldm9sdXRpb25hcnkgdHJlYXRtZW50YCBoYXMgb24gZml0bmVzcy4NCg0KKipGaXhlZCBlZmZlY3RzKioNCg0KYEJsb2NrYDogZml0bmVzcyBtaWdodCBkaWZmZXIgYmV0d2VlbiB0aGUgdGhyZWUgZGlzdGluY3QgYmxvY2tzIHdlIHNwbGl0IG91ciBleHBlcmltZW50IHVwIGludG8uIEJsb2NrcyBkaWZmZXJlZCB0ZW1wb3JhbGx5LCB1c2VkIGZsaWVzIGZyb20gZGlmZmVyZW50IGdlbmVyYXRpb25zIGFuZCBkaWZmZXJlbnQgYmF0Y2hlcyBvZiBmb29kLiBJdCBpcyBhbHNvIHBvc3NpYmxlIHRoYXQgdGhlcmUgd2VyZSBtaW5vciBmbHVjdHVhdGlvbnMgaW4gdGhlIGxpZ2h0aW5nIGFuZCB0ZW1wZXJhdHVyZSBlbnZpcm9ubWVudCBleHBlcmllbmNlZCBkdXJpbmcgZGV2ZWxvcG1lbnQgYmV0d2VlbiBibG9ja3MuIEVhY2ggb2YgdGhlc2UgdmFyaWFibGVzIG1heSBpbnRyb2R1Y2UgdmFyaWF0aW9uIGludG8gb3VyIGZpdG5lc3MgbWVhc3VyZW1lbnRzLCB0aGF0IGNhbiBiZSBhY2NvdW50ZWQgZm9yIGJ5IGluY2x1ZGluZyB0aGUgYEJsb2NrYCB2YXJpYWJsZSBpbiBvdXIgbW9kZWwuDQoNCmBHRlBgOiBpdCBpcyBwb3NzaWJsZSB0aGF0IGZpdG5lc3MgbWF5IGJlIGFmZmVjdGVkIGJ5IHRoZSBHRlAgdHJhbnNnZW5lIGNhcnJpZWQgYnkgZWFjaCBwb3B1bGF0aW9uLiBGb3IgZXhhbXBsZSwgb25lIGNvdWxkIGltYWdpbmUgdGhhdCBhbnkgdW5pbnRlbmRlZCBmaXRuZXNzIGVmZmVjdHMgb2YgYSB0cmFuc2dlbmUgbWlnaHQgYmUgb2YgZ3JlYXRlciBtYWduaXR1ZGUgaWYgaXQgaXMgZXhwcmVzc2VkIGluIGEgbGFyZ2VyIHByb3BvcnRpb24gb2YgdGlzc3VlcywgYXMgaXMgdGhlIGNhc2UgZm9yIHRoZSBfVUJJXyB0cmFuc2dlbmUgdmVyc3VzIHRoZSBfM3hQXyB0cmFuc2dlbmUuIE5vdGUgdGhhdCBlYWNoIEdGUCB0eXBlIGlzIGNhcnJpZWQgYnkgYW4gZXF1YWwgbnVtYmVyIG9mIHBvcHVsYXRpb25zIGZyb20gZWFjaCBvZiB0aGUgdGhyZWUgZXZvbHV0aW9uYXJ5IHRyZWF0bWVudHMuDQoNCmBFdm9sdXRpb25hcnlfdHJlYXRtZW50YDogdGhpcyBpcyB0aGUgaW5oZXJpdGFuY2UgcmVnaW1lIHRoYXQgdGhlIGF1dG9zb21lcyBjYXJyaWVkIGJ5IGVhY2ggb2YgdGhlIHBvcHVsYXRpb25zIHdlcmUgc3ViamVjdCB0byBmb3IgMjAgZ2VuZXJhdGlvbnMuIFRoZXJlIGFyZSB0aHJlZSBsZXZlbHM6IHBvcHVsYXRpb25zIGNhcnJ5aW5nIGZlbWFsZS1hZGFwdGVkIGF1dG9zb21lcywgcG9wdWxhdGlvbnMgY29udGFpbmluZyBtYWxlLWFkYXB0ZWQgYXV0b3NvbWVzIGFuZCBwb3B1bGF0aW9ucyBjYXJyeWluZyBjb250cm9sIGF1dG9zb21lcyB0aGF0IGV4cGVyaWVuY2VkIGFuIHVubWFuaXB1bGF0ZWQgaW5oZXJpdGFuY2UgcmVnaW1lLiBXZSBhcmUgZGVzaWduaW5nIG91ciBtb2RlbCB0byB0ZXN0IGZvciBhIGNhdXNhbCBlZmZlY3Qgb2YgdGhpcyB2YXJpYWJsZS4NCg0KKipSYW5kb20gZWZmZWN0cyoqDQoNCmBSZWFyaW5nX3ZpYWxgOiB0aGUgdmlhbCBpbmRpdmlkdWFsIGZsaWVzIGRldmVsb3BlZCB3aXRoaW4gbWF5IGludHJvZHVjZSBmdXJ0aGVyIHZhcmlhdGlvbiBpbnRvIG91ciByZXNwb25zZSB2YXJpYWJsZS4gTGlrZSBgQmxvY2tgIHRoaXMgdmFyaWFibGUgY29udHJvbHMgZm9yIG1pY3JvLWVudmlyb25tZW50YWwgdmFyaWF0aW9uLg0KDQpgUG9wdWxhdGlvbmA6IG91ciBkZXNpZ24gY29udGFpbmVkIDEyIGluZGVwZW5kZW50IHBvcHVsYXRpb25zIG9mIGF1dG9zb21lcyB0aGF0IG9yaWdpbmF0ZWQgZnJvbSBhIHNpbmdsZSBvdXRicmVkIGxhYm9yYXRvcnkgZmx5IHBvcHVsYXRpb24uIFRoZSBwb3B1bGF0aW9ucyB3ZXJlIHNwbGl0IGFuZCBhdXRvc29tZXMgZnJvbSBlYWNoIHdlcmUgc3ViamVjdGVkIHRvIG9uZSBvZiB0aGUgdGhyZWUgZXZvbHV0aW9uIHRyZWF0bWVudHMgZm9yIDIwIGdlbmVyYXRpb25zLiA0IHBvcHVsYXRpb25zIGV4cGVyaWVuY2VkIGEgZmVtYWxlLWxpbWl0ZWQgaW5oZXJpdGFuY2UgcmVnaW1lLCA0IGEgbWFsZS1saW1pdGVkIHJlZ2ltZSBhbmQgNCBhbiB1bmxpbWl0ZWQgb3IgY29udHJvbCByZWdpbWUuIA0KDQokfiQNCg0KIyBGZW1hbGUgZml0bmVzcw0KDQokfiQNCg0KVG8gZXN0aW1hdGUgdGhlIGZpdG5lc3Mgb2YgZmVtYWxlcyBjYXJyeWluZyBlYWNoIG9mIHRoZSB0aHJlZSBhdXRvc29tZSB0eXBlcywgd2UgcGxhY2VkIHRocmVlIGV4cGVyaW1lbnRhbCBmZW1hbGVzIGludG8gYSB5ZWFzdGVkIHZpYWwgd2l0aCB0aHJlZSBmZW1hbGUgY29tcGV0aXRvcnMgdGhhdCBjYXJyaWVkIHRoZSBfYndfIG11dGF0aW9uLiBXZSB0aGVuIGludHJvZHVjZWQgc2l4IG1hbGVzIHRoYXQgYWxzbyBjYXJyaWVkIHRoZSBfYndfIG11dGF0aW9uLiBXZSBhbGxvd2VkIHRoZW0gdG8gbWF0ZSBhbmQgb3ZpcG9zaXQgZm9yIHRocmVlIGRheXMsIHRoZW4gcmVtb3ZlZCBhbGwgYWR1bHRzIGZyb20gdGhlIHZpYWwuIDEyIGRheXMgbGF0ZXIgd2UgY291bnRlZCBhbGwgb2YgdGhlIGFkdWx0IHByb2dlbnkgaW4gdGhlIHZpYWwgYW5kIHNjb3JlZCB0aGVtIGZvciBleWUtY29sb3VyLiBQcm9nZW55IHdpdGggcmVkIGV5ZXMgd2VyZSBwcm9kdWNlZCBieSB0aGUgZXhwZXJpbWVudGFsIGZlbWFsZXMgKCBfYndfIGlzIHJlY2Vzc2l2ZSkgYW5kIHByb2dlbnkgd2l0aCBicm93biBleWVzIHdlcmUgcHJvZHVjZWQgYnkgdGhlIGNvbXBldGl0b3IgZmVtYWxlcy4gV2UgY2FsY3VsYXRlZCBmaXRuZXNzIGFzIHRoZSBwcm9wb3J0aW9uIG9mIHJlZCBleWVkIG9mZnNwcmluZyBpbiB0aGUgdmlhbC4gDQoNCiR+JA0KDQojIyBNb2RlbGxpbmcNCg0KYGBge3J9DQpmZW1hbGVfZml0bmVzcy4wMSA8LQ0KICBicm0oVG90YWxfcmVkX29mZnNwcmluZyB8IHRyaWFscyhUb3RhbF9vZmZzcHJpbmcpIH4gMSArIEV2b2x1dGlvbmFyeV90cmVhdG1lbnQgKyBHRlAgKyBCbG9jayArICgxfFBvcHVsYXRpb24pICsgKDF8UmVhcmluZ192aWFsKSwNCiAgICAgIGRhdGEgPSBmZW1hbGVfZml0bmVzcywgZmFtaWx5ID0gYmlub21pYWwoKSwgDQogICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDEuNSksIGNsYXNzID0gSW50ZXJjZXB0KSwNCiAgICAgICAgICAgICAgICBwcmlvcihub3JtYWwoMCwgMiksIGNsYXNzID0gYiksDQogICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gc2QpKSwNCiAgICAgIGl0ZXIgPSAxMDAwMCwgd2FybXVwID0gODAwMCwgY2hhaW5zID0gNCwgY29yZXMgPSA0LA0KICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgIHNlZWQgPSAyLCBmaWxlID0gIkZpdHMvZmVtYWxlX2ZpdG5lc3MuMDEiKQ0KDQpwcmludChmZW1hbGVfZml0bmVzcy4wMSkNCg0KYGBgDQoNCkxldHMgc2VlIGlmIHdlIGhhdmUgYW55IHBvaW50cyB0aGF0IGhhdmUgYSBzdHJvbmcgaW5mbHVlbmNlIG9uIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uDQoNCmBgYHtyfQ0KDQojZmVtYWxlX2ZpdG5lc3MuMDEgPC0gYWRkX2NyaXRlcmlvbihmZW1hbGVfZml0bmVzcy4wMSwgY3JpdGVyaW9uID0gImxvbyIsIGZpbGUgPSAiZml0cy9mZW1hbGVfZml0bmVzcy4wMSIpDQoNCiNmZW1hbGVfZml0bmVzcy4wMSA8LSBhZGRfY3JpdGVyaW9uKGZlbWFsZV9maXRuZXNzLjAxLCBjcml0ZXJpb24gPSAid2FpYyIsIGZpbGUgPSAiZml0cy9mZW1hbGVfZml0bmVzcy4wMSIpDQoNCmxvbyhmZW1hbGVfZml0bmVzcy4wMSkNCg0KYGBgDQoNClRoZXJlIGFwcGVhciB0byBiZSBtYW55IHBvaW50cyB0aGF0IGFyZSBoaWdobHkgaW5mbHVlbnRpYWwgb24gdGhlIHBvc3Rlcmlvci4gV2h5PyBJdCBhcHBlYXJzIHRoYXQgdGhpcyBpcyBleHBsYWluZWQgYnkgc21hbGwgc2FtcGxlIHNpemVzIGZvciBzb21lIG9mIHRoZSByZWFyaW5nIHZpYWxzLiBGb3IgZXhhbXBsZSwgZmVtYWxlIGZsaWVzIHJlYXJlZCBpbiB2aWFsIDI0IGFyZSBvbmx5IHVzZWQgaW4gYSBzaW5nbGUgZml0bmVzcyBhc3NheSwgbWFraW5nIGVzdGltYXRpb24gZm9yIHRoaXMgdmlhbCB2ZXJ5IGRpZmZpY3VsdC4gSXQgYWxzbyBtZWFucyB0aGF0IHRoZSBzaW5nbGUgb2JzZXJ2YXRpb24gZm9yIHRoYXQgdmlhbCBoYXMgYSBodWdlIGVmZmVjdCBvbiBpdHMgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiwgd2hpY2ggcmV0dXJucyBhIHZlcnkgaGlnaCBwYXJldG8gayB2YWx1ZS4gDQoNClRoZXJlIGFyZSBzZXZlcmFsIHdheXMgdG8gbGltaXQgdGhlIGluZmx1ZW5jZSBvZiB0aGVzZSAnb3V0bGllcnMnIG9uIHRoZSBwb3N0ZXJpb3IuIFRoZSBmaXJzdCBpcyB0byByZW1vdmUgYFJlYXJpbmdfdmlhbGAgZnJvbSB0aGUgbW9kZWwuIFdoaWxlIG5vdCBydW4gaGVyZSwgdGhpcyByZWR1Y2VzIHRoZSBudW1iZXIgb2YgaGlnaGx5IGluZmx1ZW50aWFsIHBvaW50cyB0byAwLiBBbHRlcm5hdGl2ZWx5LCB3ZSBjYW4gc3BlY2lmeSBhIGRpZmZlcmVudCBkaXN0cmlidXRpb24gZmFtaWx5IHRoYXQgaXMgYmV0dGVyIGVxdWlwcGVkIHRvIGRlYWwgd2l0aCBleHRyZW1lIHZhbHVlcyBhdCB0aGUgdGFpbHMuIFRoaXMgYWxsb3dzIHVzIHRvIGFjY291bnQgZm9yIHRoZSBwb3RlbnRpYWxseSBpbXBvcnRhbnQgdmFyaWF0aW9uIGNvZGVkIGJ5IGBSZWFyaW5nX3ZpYWxgLiBBIG1vcmUgZmxleGlibGUgdmVyc2lvbiBvZiB0aGUgYGJpbm9taWFsYCBpcyB0aGUgYGJldGFiaW5vbWlhbGAuDQoNCkhvd2V2ZXIsIHRoZSBiZXRhLWJpbm9taWFsIGlzIG5vdCBhIG5hdGl2ZSBmYW1pbHkgaW4gYGJybXNgLCB3ZSBuZWVkIHRvIGNyZWF0ZSB0aGUgZGlzdHJpYnV0aW9uIGZhbWlseSB1c2luZyB0aGUgYGN1c3RvbV9mYW1pbHkoKWAgZnVuY3Rpb24uIFRoZSBjb2RlIGJlbG93IGlzIHRha2VuIGRpcmVjdGx5IGZyb20gdGhlIGBicm1zX2N1c3RvbWZhbWlsaWVzYCB2aWduZXR0ZSwgd2hpY2ggY2FuIGJlIHZpZXdlZCBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2JybXMvdmlnbmV0dGVzL2JybXNfY3VzdG9tZmFtaWxpZXMuaHRtbCkuDQoNCmBgYHtyfQ0KYmV0YV9iaW5vbWlhbDIgPC0gY3VzdG9tX2ZhbWlseSgNCiAgImJldGFfYmlub21pYWwyIiwgZHBhcnMgPSBjKCJtdSIsICJwaGkiKSwNCiAgbGlua3MgPSBjKCJsb2dpdCIsICJsb2ciKSwgbGIgPSBjKE5BLCAwKSwNCiAgdHlwZSA9ICJpbnQiLCB2YXJzID0gInZpbnQxW25dIg0KKQ0KDQoNCnN0YW5fZnVucyA8LSAiDQogIHJlYWwgYmV0YV9iaW5vbWlhbDJfbHBtZihpbnQgeSwgcmVhbCBtdSwgcmVhbCBwaGksIGludCBUKSB7DQogICAgcmV0dXJuIGJldGFfYmlub21pYWxfbHBtZih5IHwgVCwgbXUgKiBwaGksICgxIC0gbXUpICogcGhpKTsNCiAgfQ0KICBpbnQgYmV0YV9iaW5vbWlhbDJfcm5nKHJlYWwgbXUsIHJlYWwgcGhpLCBpbnQgVCkgew0KICAgIHJldHVybiBiZXRhX2Jpbm9taWFsX3JuZyhULCBtdSAqIHBoaSwgKDEgLSBtdSkgKiBwaGkpOw0KICB9DQoiDQoNCnN0YW52YXJzIDwtIHN0YW52YXIoc2NvZGUgPSBzdGFuX2Z1bnMsIGJsb2NrID0gImZ1bmN0aW9ucyIpDQoNCmBgYA0KDQpCZWxvdyB3ZSBmaXQgdGhlIHNhbWUgbW9kZWwsIGJ1dCB0aGlzIHRpbWUgc3BlY2lmeSBhIGJldGEtYmlub21pYWwgZGlzdHJpYnV0aW9uLg0KDQpgYGB7cn0NCmZlbWFsZV9maXRuZXNzLjAyIDwtDQogIGJybShUb3RhbF9yZWRfb2Zmc3ByaW5nIHwgdmludChUb3RhbF9vZmZzcHJpbmcpIH4gMSArIEV2b2x1dGlvbmFyeV90cmVhdG1lbnQgKyBHRlAgKyBCbG9jayArICgxfFBvcHVsYXRpb24pICsgKDF8UmVhcmluZ192aWFsKSwNCiAgICAgIGRhdGEgPSBmZW1hbGVfZml0bmVzcywgZmFtaWx5ID0gYmV0YV9iaW5vbWlhbDIsIA0KICAgICAgcHJpb3IgPSBjKHByaW9yKG5vcm1hbCgwLCAxLjUpLCBjbGFzcyA9IEludGVyY2VwdCksDQogICAgICAgICAgICAgICAgcHJpb3Iobm9ybWFsKDAsIDIpLCBjbGFzcyA9IGIpLA0KICAgICAgICAgICAgICAgIHByaW9yKGV4cG9uZW50aWFsKDEpLCBjbGFzcyA9IHNkKSksDQogICAgICBpdGVyID0gMTAwMDAsIHdhcm11cCA9IDgwMDAsIGNoYWlucyA9IDQsIGNvcmVzID0gNCwNCiAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45NSwgbWF4X3RyZWVkZXB0aCA9IDEwKSwNCiAgICAgIHNlZWQgPSAyLCBzdGFudmFycyA9IHN0YW52YXJzLCBmaWxlID0gIkZpdHMvZmVtYWxlX2ZpdG5lc3MuMDIiKQ0KDQpwcmludChmZW1hbGVfZml0bmVzcy4wMikNCg0KDQojZmVtYWxlX2ZpdG5lc3MuMDIgPC0gYWRkX2NyaXRlcmlvbihmZW1hbGVfZml0bmVzcy4wMiwgY3JpdGVyaW9uID0gImxvbyIsIGZpbGUgPSAiZml0cy9mZW1hbGVfZml0bmVzcy4wMiIpDQoNCiNmZW1hbGVfZml0bmVzcy4wMiA8LSBhZGRfY3JpdGVyaW9uKGZlbWFsZV9maXRuZXNzLjAyLCBjcml0ZXJpb24gPSAid2FpYyIsIGZpbGUgPSAiZml0cy9mZW1hbGVfZml0bmVzcy4wMiIpDQoNCmBgYA0KDQpXZSBuZWVkIHRvIHdyaXRlIHNvbWUgYWRkaXRpb25hbCBjb2RlIHRvIGdldCBzb21lIHBvc3QgcHJvY2Vzc2luZyBzdHVmZiBpLmUuIExPTyB0byB3b3JrLiBDb2RlIGNvdXJ0ZXN5IG9mIHRoZSBgYnJtc19jdXN0b21mYW1pbGllc2AgdmlnbmV0dGUsIHdoaWNoIGNhbiBiZSB2aWV3ZWQgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9icm1zL3ZpZ25ldHRlcy9icm1zX2N1c3RvbWZhbWlsaWVzLmh0bWwpLg0KDQpgYGB7cn0NCiMgd2UgbmVlZCB0byB3cml0ZSBzb21lIGFkZGl0aW9uYWwgY29kZSB0byBnZXQgc29tZSBwb3N0LXByb2Nlc3Npbmcgc3R1ZmYgdG8gd29yaw0KDQpleHBvc2VfZnVuY3Rpb25zKGZlbWFsZV9maXRuZXNzLjAyLCB2ZWN0b3JpemUgPSBUUlVFKQ0KDQoNCmxvZ19saWtfYmV0YV9iaW5vbWlhbDIgPC0gZnVuY3Rpb24oaSwgcHJlcCkgew0KICBtdSA8LSBicm1zOjpnZXRfZHBhcihwcmVwLCAibXUiLCBpID0gaSkNCiAgcGhpIDwtIGJybXM6OmdldF9kcGFyKHByZXAsICJwaGkiLCBpID0gaSkNCiAgdHJpYWxzIDwtIHByZXAkZGF0YSR2aW50MVtpXQ0KICB5IDwtIHByZXAkZGF0YSRZW2ldDQogIGJldGFfYmlub21pYWwyX2xwbWYoeSwgbXUsIHBoaSwgdHJpYWxzKQ0KfQ0KDQpwb3N0ZXJpb3JfcHJlZGljdF9iZXRhX2Jpbm9taWFsMiA8LSBmdW5jdGlvbihpLCBwcmVwLCAuLi4pIHsNCiAgbXUgPC0gYnJtczo6Z2V0X2RwYXIocHJlcCwgIm11IiwgaSA9IGkpDQogIHBoaSA8LSBicm1zOjpnZXRfZHBhcihwcmVwLCAicGhpIiwgaSA9IGkpDQogIHRyaWFscyA8LSBwcmVwJGRhdGEkdmludDFbaV0NCiAgYmV0YV9iaW5vbWlhbDJfcm5nKG11LCBwaGksIHRyaWFscykNCn0NCg0KcG9zdGVyaW9yX2VwcmVkX2JldGFfYmlub21pYWwyIDwtIGZ1bmN0aW9uKHByZXApIHsNCiAgbXUgPC0gYnJtczo6Z2V0X2RwYXIocHJlcCwgIm11IikNCiAgdHJpYWxzIDwtIHByZXAkZGF0YSR2aW50MQ0KICB0cmlhbHMgPC0gbWF0cml4KHRyaWFscywgbnJvdyA9IG5yb3cobXUpLCBuY29sID0gbmNvbChtdSksIGJ5cm93ID0gVFJVRSkNCiAgbXUgKiB0cmlhbHMNCn0NCmBgYA0KDQpSdW4gTE9PIHRvIHNlZSBpZiB3ZSd2ZSBoYW5kbGVkIHRoZSBpbmZsdWVudGlhbCBwb2ludHMgYW5kIHRoZW4gcmFuayBtb2RlbHMgd2l0aCB0aGUgYGxvb19jb21wYXJlKClgIGZ1bmN0aW9uLg0KDQpgYGB7cn0NCg0KbG9vKGZlbWFsZV9maXRuZXNzLjAyKQ0KDQpsb29fY29tcGFyZShmZW1hbGVfZml0bmVzcy4wMSwgZmVtYWxlX2ZpdG5lc3MuMDIsIGNyaXRlcmlvbiA9ICJ3YWljIikNCg0KYGBgDQoNClRoZSBiZXRhLWJpbm9taWFsIG1vZGVsIGxvb2tzIGdvb2QuIEl0IGZpeGVzIG91ciBpbmZsdWVudGlhbCBwb2ludHMgcHJvYmxlbSBhbmQgaXMgcHJlZmVycmVkIGJ5IHRoZSBMT08gbWV0cmljLg0KDQpDb25kdWN0IGEgcG9zdGVyaW9yIHByZWRpY3RpdmUgY2hlY2sgdG8gY29uZmlybSBvdXIgbW9kZWwgaXMgZG9pbmcgd2hhdCB3ZSB3YW50IGl0IHRvLg0KDQpgYGB7cn0NCnBwX2NoZWNrKGZlbWFsZV9maXRuZXNzLjAyLCB0eXBlID0gImhpc3QiLCBuZHJhd3MgPSAxMSwgYmlud2lkdGggPSAxMCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNClRoZSBwb3N0ZXJpb3IgcHJlZGljdGl2ZSBkaXN0cmlidXRpb24gbWF0Y2hlcyBvdXIgcmF3IGRhdGEgcXVpdGUgd2VsbCwgaW5kaWNhdGluZyB0aGUgbW9kZWwgaXMgZnVuY3Rpb25pbmcgYXMgd2Ugd2FudGVkLg0KDQokfiQNCg0KIyMgRGVyaXZlIHByZWRpY3Rpb25zIGZyb20gdGhlIHBvc3Rlcmlvcg0KDQpHZXQgcHJlZGljdGlvbnMgZnJvbSB0aGUgbW9kZWwgYW5kIHByZXNlbnQgdGhlbSBpbiBhIFRhYmxlDQoNCmBgYHtyfQ0KDQpkcmF3cyA8LSBhc19kcmF3c19kZihmZW1hbGVfZml0bmVzcy4wMikNCg0KZHJhd3NfZmVtYWxlIDwtDQogIGRyYXdzICAlPiUgDQogIG11dGF0ZShgRmVtYWxlLWxpbWl0ZWRgID0gaW52X2xvZ2l0X3NjYWxlZChiX0ludGVyY2VwdCArIGJfRXZvbHV0aW9uYXJ5X3RyZWF0bWVudEZlbWFsZV9saW1pdGVkKSwNCiAgICAgICAgIGBNYWxlLWxpbWl0ZWRgID0gaW52X2xvZ2l0X3NjYWxlZChiX0ludGVyY2VwdCArIGJfRXZvbHV0aW9uYXJ5X3RyZWF0bWVudE1hbGVfbGltaXRlZCksDQogICAgICAgICBDb250cm9sID0gaW52X2xvZ2l0X3NjYWxlZChiX0ludGVyY2VwdCkpICU+JSANCiAgc2VsZWN0KENvbnRyb2wsIGBGZW1hbGUtbGltaXRlZGAsIGBNYWxlLWxpbWl0ZWRgKSAlPiUgDQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKENvbnRyb2wsIGBGZW1hbGUtbGltaXRlZGAsIGBNYWxlLWxpbWl0ZWRgKSwNCiAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiRXZvbHV0aW9uYXJ5X3RyZWF0bWVudCIpICU+JSANCiAgcmVuYW1lKHByb3BfZm9jYWxfb2Zmc3ByaW5nID0gdmFsdWUpICU+JSANCiAgYXJyYW5nZShFdm9sdXRpb25hcnlfdHJlYXRtZW50KQ0KDQpkcmF3c19mZW1hbGUgJT4lIA0KICBncm91cF9ieShFdm9sdXRpb25hcnlfdHJlYXRtZW50KSAlPiUgDQogIHN1bW1hcmlzZShgRXN0aW1hdGVkIHByb3AuIG9mIG9mZnNwcmluZyBwcm9kdWNlZGAgPSBtZWRpYW4ocHJvcF9mb2NhbF9vZmZzcHJpbmcpLA0KICAgICAgICAgICAgYDIuNSVgID0gcXVhbnRpbGUocHJvcF9mb2NhbF9vZmZzcHJpbmcsIHByb2JzID0gMC4wMjUpLA0KICAgICAgICAgICAgYDk3LjUlYCA9IHF1YW50aWxlKHByb3BfZm9jYWxfb2Zmc3ByaW5nLCBwcm9icyA9IDAuOTc1KSkgJT4lIA0KICByZW5hbWUoYEluaGVyaXRhbmNlIHRyZWF0bWVudGAgPSBFdm9sdXRpb25hcnlfdHJlYXRtZW50KSAlPiUgDQogIHBhbmRlcihzcGxpdC5jZWxsID0gNDAsIHNwbGl0LnRhYmxlID0gSW5mLCByb3VuZCA9IDMpDQoNCiMgbm93IGZpbmQgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGNvbnRyb2wgYW5kIHRoZSBzZXgtbGltaXRlZCB0cmVhdG1lbnRzDQoNCiMgdGhlIGludl9sb2dpdF9zY2FsZWQoKSBmdW5jdGlvbiBjb252ZXJ0cyB0aGUgcG9zdGVyaW9yIGRyYXdzIG9udG8gdGhlIHJlc3BvbnNlIHNjYWxlIA0KDQogIGRyYXdzICU+JSANCiAgbXV0YXRlKHBfY29udHJvbCA9ICBpbnZfbG9naXRfc2NhbGVkKGJfSW50ZXJjZXB0KSwNCiAgICAgICAgIHBfZmVtYWxlID0gaW52X2xvZ2l0X3NjYWxlZChiX0V2b2x1dGlvbmFyeV90cmVhdG1lbnRGZW1hbGVfbGltaXRlZCArIGJfSW50ZXJjZXB0KSwNCiAgICAgICAgIHBfbWFsZSA9IGludl9sb2dpdF9zY2FsZWQoYl9Fdm9sdXRpb25hcnlfdHJlYXRtZW50TWFsZV9saW1pdGVkICsgYl9JbnRlcmNlcHQpLA0KICAgICAgICAgYEZlbWFsZS1saW1pdGVkYCA9IHBfZmVtYWxlIC8gcF9jb250cm9sLA0KICAgICAgICAgYE1hbGUtbGltaXRlZGAgPSBwX21hbGUgLyBwX2NvbnRyb2wpICU+JSANCiAgZ2F0aGVyKGtleSA9IGBkaWZmZXJlbmNlIGNvbXBhcmlzb25gLCB2YWx1ZSA9IGAlIGRpZmZlcmVuY2VgKSAlPiUgDQogIGZpbHRlcihgZGlmZmVyZW5jZSBjb21wYXJpc29uYCA9PSBjKCJGZW1hbGUtbGltaXRlZCIsICJNYWxlLWxpbWl0ZWQiKSkgJT4lIA0KICBncm91cF9ieShgZGlmZmVyZW5jZSBjb21wYXJpc29uYCkgICU+JSANCiAgc3VtbWFyaXNlKGBNZWFuIHByb3BvcnRpb24gb2Ygb2Zmc3ByaW5nIHByb2R1Y2VkIHJlbGF0aXZlIHRvIGNvbnRyb2xgICA9IG1lYW4oYCUgZGlmZmVyZW5jZWApLA0KICAgICAgICAgICAgYDIuNSVgID0gcXVhbnRpbGUoYCUgZGlmZmVyZW5jZWAsIHByb2JzID0gMC4wMjUpLA0KICAgICAgICAgICAgYDk3LjUlYCA9IHF1YW50aWxlKGAlIGRpZmZlcmVuY2VgLCBwcm9icyA9IDAuOTc1KSkgJT4lIA0KICByZW5hbWUoYEluaGVyaXRhbmNlIHRyZWF0bWVudGAgPSBgZGlmZmVyZW5jZSBjb21wYXJpc29uYCkgJT4lIA0KICBwYW5kZXIoc3BsaXQuY2VsbCA9IDQwLCBzcGxpdC50YWJsZSA9IEluZiwgcm91bmQgPSAzKQ0KYGBgDQoNCiR+JA0KDQojIE1hbGUgZml0bmVzcw0KDQokfiQNCg0KVG8gZXN0aW1hdGUgdGhlIGZpdG5lc3Mgb2YgbWFsZXMgY2FycnlpbmcgZWFjaCBvZiB0aGUgdGhyZWUgY2hyb21vc29tZSB0eXBlcywgd2UgY29uZHVjdGVkIGFuIGV4cGVyaW1lbnQgdmVyeSBzaW1pbGFyIHRvIHRoZSBmZW1hbGUgZml0bmVzcyBhc3NheS4gSG93ZXZlciwgYmVjYXVzZSBtYWxlIGZpdG5lc3MgaGFzIHN0cm9uZ2VyIGNvdmFyaWFuY2Ugd2l0aCBmZXJ0aWxpc2F0aW9uIGV2ZW50cyB0aGFuIGRvZXMgZmVtYWxlIGZpdG5lc3MsIHdlIGNvbmR1Y3RlZCB0aGUgbWFsZSBmaXRuZXNzIGFzc2F5IHdpdGggYSAxOjIgc2V4IHJhdGlvIChmZW1hbGU6bWFsZSkgcmF0aGVyIHRoYW4gdGhlIDE6MSByYXRpbyB1c2VkIGluIHRoZSBmZW1hbGUgYXNzYXkuIFRoaXMgaW5jcmVhc2VzIHRoZSBzdHJlbmd0aCBvZiBzZXh1YWwgc2VsZWN0aW9uIGFuZCBpcyBhIG1vcmUgYXBwb3ByaWF0ZSB3YXkgdG8gZXhwb3NlIGRpZmZlcmVuY2VzIGluIGZpdG5lc3MgYmV0d2VlbiBncm91cHMgb2YgbWFsZXMuIEFzIHdpdGggdGhlIGZlbWFsZXMsIHdlIGNhbGN1bGF0ZWQgZml0bmVzcyBhcyB0aGUgcHJvcG9ydGlvbiBvZiByZWQgZXllZCBvZmZzcHJpbmcgaW4gdGhlIHZpYWwuIA0KDQojIyBBbHRlcm5hdGl2ZSBtb2RlbGxpbmcgYXBwcm9hY2hlcyB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMgQmlub21pYWwgbW9kZWwgd2l0aCByZWFyaW5nIHZpYWwNCg0KYGBge3J9DQptYWxlX2ZpdG5lc3MuMDEgPC0NCiAgYnJtKFRvdGFsX3JlZF9vZmZzcHJpbmcgfCB0cmlhbHMoVG90YWxfb2Zmc3ByaW5nKSB+IDEgKyBFdm9sdXRpb25hcnlfdHJlYXRtZW50ICsgR0ZQICsgQmxvY2sgKyAoMXxQb3B1bGF0aW9uKSArICgxfFJlYXJpbmdfdmlhbCksDQogICAgICBkYXRhID0gbWFsZV9maXRuZXNzLCBmYW1pbHkgPSBiaW5vbWlhbCgpLCANCiAgICAgIHByaW9yID0gYyhwcmlvcihub3JtYWwoMCwgMS41KSwgY2xhc3MgPSBJbnRlcmNlcHQpLA0KICAgICAgICAgICAgICAgIHByaW9yKG5vcm1hbCgwLCAyKSwgY2xhc3MgPSBiKSwNCiAgICAgICAgICAgICAgICBwcmlvcihleHBvbmVudGlhbCgxKSwgY2xhc3MgPSBzZCkpLA0KICAgICAgaXRlciA9IDEwMDAwLCB3YXJtdXAgPSA4MDAwLCBjaGFpbnMgPSA0LCBjb3JlcyA9IDQsDQogICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgc2VlZCA9IDIsIGZpbGUgPSAiRml0cy9tYWxlX2ZpdG5lc3MuMDEiKQ0KDQoNCnByaW50KG1hbGVfZml0bmVzcy4wMSkNCmBgYA0KDQpMaWtlIHdpdGggdGhlIGZlbWFsZSBmaXRuZXNzIG1vZGVsLCBsZXRzIHNlZSBpZiB3ZSBoYXZlIGFueSBwb2ludHMgdGhhdCBoYXZlIGEgc3Ryb25nIGluZmx1ZW5jZSBvbiB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbi4gUnVuIExPTzoNCg0KYGBge3J9DQoNCiNtYWxlX2ZpdG5lc3MuMDEgPC0gYWRkX2NyaXRlcmlvbihtYWxlX2ZpdG5lc3MuMDQsIGNyaXRlcmlvbiA9ICJsb28iLCBmaWxlID0gImZpdHMvbWFsZV9maXRuZXNzLjA0IikNCiNtYWxlX2ZpdG5lc3MuMDEgPC0gYWRkX2NyaXRlcmlvbihtYWxlX2ZpdG5lc3MuMDEsIGNyaXRlcmlvbiA9ICJ3YWljIiwgZmlsZSA9ICJmaXRzL21hbGVfZml0bmVzcy4wMSIpDQoNCmxvbyhtYWxlX2ZpdG5lc3MuMDEpDQoNCmBgYA0KDQpDb25kdWN0IHRoZSBwb3N0ZXJpb3IgcHJlZGljdGl2ZSBjaGVjay4uLg0KDQpgYGB7cn0NCnBwX2NoZWNrKG1hbGVfZml0bmVzcy4wMSwgdHlwZSA9ICJoaXN0IiwgbmRyYXdzID0gMTEsIGJpbndpZHRoID0gMTApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkNCmBgYA0KDQoNCiMjIyBCaW5vbWlhbCBtb2RlbCB3aXRob3V0IHJlYXJpbmcgdmlhbA0KDQpMaWtlIHdpdGggdGhlIGZlbWFsZSBtb2RlbCwgdGhlcmUgYXBwZWFycyB0byBiZSBtYW55IHBvaW50cyB0aGF0IGFyZSBoaWdobHkgaW5mbHVlbnRpYWwgb24gdGhlIHBvc3Rlcmlvci4gSSByZW1vdmUgYFJlYXJpbmdfdmlhbGAgb25jZSBtb3JlIHRvIHNlZSBpZiB0aGlzIGlzIHRoZSB2YXJpYWJsZSByZXNwb25zaWJsZSBmb3IgbWFraW5nIGNlcnRhaW4gcG9pbnRzIGhpZ2hseSBpbmZsdWVudGlhbC4NCg0KYGBge3J9DQptYWxlX2ZpdG5lc3MuMDIgPC0NCiAgYnJtKFRvdGFsX3JlZF9vZmZzcHJpbmcgfCB0cmlhbHMoVG90YWxfb2Zmc3ByaW5nKSB+IDEgKyBFdm9sdXRpb25hcnlfdHJlYXRtZW50ICsgR0ZQICsgQmxvY2sgKyAoMXxQb3B1bGF0aW9uKSwNCiAgICAgIGRhdGEgPSBtYWxlX2ZpdG5lc3MsIGZhbWlseSA9IGJpbm9taWFsKCksIA0KICAgICAgcHJpb3IgPSBjKHByaW9yKG5vcm1hbCgwLCAxLjUpLCBjbGFzcyA9IEludGVyY2VwdCksDQogICAgICAgICAgICAgICAgcHJpb3Iobm9ybWFsKDAsIDIpLCBjbGFzcyA9IGIpLA0KICAgICAgICAgICAgICAgIHByaW9yKGV4cG9uZW50aWFsKDEpLCBjbGFzcyA9IHNkKSksDQogICAgICBpdGVyID0gNDAwMCwgd2FybXVwID0gMjAwMCwgY2hhaW5zID0gNCwgY29yZXMgPSA0LA0KICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjgsIG1heF90cmVlZGVwdGggPSAxMCksDQogICAgICBzZWVkID0gMiwgZmlsZSA9ICJGaXRzL21hbGVfZml0bmVzcy4wMiIpDQoNCmBgYA0KDQpSdW4gTE9PDQoNCmBgYHtyfQ0KDQojbWFsZV9maXRuZXNzLjAyIDwtIGFkZF9jcml0ZXJpb24obWFsZV9maXRuZXNzLjAyLCBjcml0ZXJpb24gPSAibG9vIiwgZmlsZSA9ICJmaXRzL21hbGVfZml0bmVzcy4wMiIpDQoNCiNtYWxlX2ZpdG5lc3MuMDIgPC0gYWRkX2NyaXRlcmlvbihtYWxlX2ZpdG5lc3MuMDIsIGNyaXRlcmlvbiA9ICJ3YWljIiwgZmlsZSA9ICJmaXRzL21hbGVfZml0bmVzcy4wMiIpDQoNCmxvbyhtYWxlX2ZpdG5lc3MuMDIpDQoNCmBgYA0KDQoNCkNvbmR1Y3QgdGhlIHBvc3RlcmlvciBwcmVkaWN0aXZlIGNoZWNrLi4uDQoNCmBgYHtyfQ0KcHBfY2hlY2sobWFsZV9maXRuZXNzLjAyLCB0eXBlID0gImhpc3QiLCBuZHJhd3MgPSAxMSwgYmlud2lkdGggPSAxMCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCg0KUmVtb3ZpbmcgYFJlYXJpbmdfdmlhbGAgcmVkdWNlcyB0aGUgbnVtYmVyIG9mIGhpZ2hseSBpbmZsdWVudGlhbCBwb2ludHMsIGhvd2V2ZXIgdGhpcyB0aW1lIDE0IHJlbWFpbi4uLg0KDQojIyMgQmV0YS1iaW5vbWlhbCBtb2RlbA0KDQpgYGB7cn0NCm1hbGVfZml0bmVzcy4wMyA8LQ0KICBicm0oVG90YWxfcmVkX29mZnNwcmluZyB8IHZpbnQoVG90YWxfb2Zmc3ByaW5nKSB+IDEgKyBFdm9sdXRpb25hcnlfdHJlYXRtZW50ICsgR0ZQICsgQmxvY2sgKyAoMXxQb3B1bGF0aW9uKSArICgxfFJlYXJpbmdfdmlhbCksDQogICAgICBkYXRhID0gbWFsZV9maXRuZXNzLCBmYW1pbHkgPSBiZXRhX2Jpbm9taWFsMiwgDQogICAgICBwcmlvciA9IGMocHJpb3Iobm9ybWFsKDAsIDEuNSksIGNsYXNzID0gSW50ZXJjZXB0KSwNCiAgICAgICAgICAgICAgICBwcmlvcihub3JtYWwoMCwgMiksIGNsYXNzID0gYiksDQogICAgICAgICAgICAgICAgcHJpb3IoZXhwb25lbnRpYWwoMSksIGNsYXNzID0gc2QpKSwNCiAgICAgIGl0ZXIgPSAxMDAwMCwgd2FybXVwID0gODAwMCwgY2hhaW5zID0gNCwgY29yZXMgPSA0LA0KICAgICAgc3RhbnZhcnMgPSBzdGFudmFycywNCiAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45LCBtYXhfdHJlZWRlcHRoID0gMTApLA0KICAgICAgc2VlZCA9IDIsIGZpbGUgPSAiRml0cy9tYWxlX2ZpdG5lc3MuMDMiKQ0KDQpwcmludChtYWxlX2ZpdG5lc3MuMDMpDQoNCg0KYGBgDQoNClF1aWNrIGJpdCBvZiBjb2RlIHRvIGdldCBvdXIgY3VzdG9tIGZhbWlseSBwb3N0LXByb2Nlc3NpbmcgdG8gd29yaw0KDQpgYGB7cn0NCmV4cG9zZV9mdW5jdGlvbnMobWFsZV9maXRuZXNzLjAzLCB2ZWN0b3JpemUgPSBUUlVFKQ0KYGBgDQoNCg0KUnVuIExPTw0KDQpgYGB7cn0NCiNtYWxlX2ZpdG5lc3MuMDMgPC0gYWRkX2NyaXRlcmlvbihtYWxlX2ZpdG5lc3MuMDMsIGNyaXRlcmlvbiA9ICJsb28iLCBmaWxlID0gImZpdHMvbWFsZV9maXRuZXNzLjAzIikNCg0KI21hbGVfZml0bmVzcy4wMyA8LSBhZGRfY3JpdGVyaW9uKG1hbGVfZml0bmVzcy4wMywgY3JpdGVyaW9uID0gIndhaWMiLCBmaWxlID0gImZpdHMvbWFsZV9maXRuZXNzLjAzIikNCg0KbG9vKG1hbGVfZml0bmVzcy4wMykNCg0KbG9vX2NvbXBhcmUobWFsZV9maXRuZXNzLjAxLCBtYWxlX2ZpdG5lc3MuMDIsIG1hbGVfZml0bmVzcy4wMywgY3JpdGVyaW9uID0gImxvbyIpDQoNCmBgYA0KDQpUaGVyZSBpcyBvbmx5IGEgc2luZ2xlIHBvaW50IG5vdyB0aGF0IExPTyBpcyB3b3JyaWVkIGFib3V0LCBldmVuIHdoaWxlIGluY2x1ZGluZyBgUmVhcmluZ192aWFsYCBhcyBhIHJhbmRvbSBlZmZlY3QuIFRoZSAqKmJldGEtYmlub21pYWwqKiBtb2RlbCBhbHNvIHBlcmZvcm1zIHRoZSBiZXN0IGJ5IHRoZSBMT08gYW5kIFdBSUMgbWV0cmljcy4NCg0KQ29uZHVjdCB0aGUgcG9zdGVyaW9yIHByZWRpY3RpdmUgY2hlY2suLi4NCg0KYGBge3J9DQpwcF9jaGVjayhtYWxlX2ZpdG5lc3MuMDMsIHR5cGUgPSAiaGlzdCIsIG5kcmF3cyA9IDExLCBiaW53aWR0aCA9IDEwKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KDQojIyMgWmVyby1vbmUtaW5mbGF0ZWQgYmV0YQ0KDQpBbm90aGVyIGludGVyZXN0aW5nIGFzcGVjdCB0byB0aGVzZSBkYXRhIGFyZSB0aGUgcHJldmFsZW5jZSBvZiAxIHZhbHVlcy4gVGhhdCBpcywgdGhlcmUgYXJlIG1hbnkgdHJpYWxzIHdoZXJlIHRoZSByZWQtZXllZCBtYWxlcyBjYXJyeWluZyB0aGUgZXhwZXJpbWVudGFsbHkgZXZvbHZlZCBhdXRvc29tZXMgc2lyZSBhbGwgb2YgdGhlIG9mZnNwcmluZyBwcm9kdWNlZCBpbiB0aGUgdmlhbC4gVGhlc2UgZXh0cmVtZSB2YWx1ZXMgYXJlIG5vdCBoYW5kbGVkIHdlbGwgYnkgYmlub21pYWwgbW9kZWxzLiBJbnN0ZWFkIHdlIGNhbiBtb2RlbCB0aGUgcHJvcG9ydGlvbiBvZiByZWQtZXllZCBvZmZzcHJpbmcgdXNpbmcgYSBgemVyby1vbmUtaW5mbGF0ZWQgYmV0YWAgbW9kZWwuDQoNCmBgYHtyfQ0KbWFsZV9maXRuZXNzLjA0IDwtDQogIGJybShwcm9wX3JlZCB+IDEgKyBFdm9sdXRpb25hcnlfdHJlYXRtZW50ICsgR0ZQICsgQmxvY2sgKyAoMXxQb3B1bGF0aW9uKSArICgxfFJlYXJpbmdfdmlhbCksDQogICAgICBkYXRhID0gbWFsZV9maXRuZXNzLCBmYW1pbHkgPSB6ZXJvX29uZV9pbmZsYXRlZF9iZXRhKCksIA0KICAgICAgcHJpb3IgPSBjKHByaW9yKG5vcm1hbCgwLCAxLjUpLCBjbGFzcyA9IEludGVyY2VwdCksDQogICAgICAgICAgICAgICAgcHJpb3Iobm9ybWFsKDAsIDIpLCBjbGFzcyA9IGIpLA0KICAgICAgICAgICAgICAgIHByaW9yKGV4cG9uZW50aWFsKDEpLCBjbGFzcyA9IHNkKSksDQogICAgICBpdGVyID0gMTAwMDAsIHdhcm11cCA9IDgwMDAsIGNoYWlucyA9IDQsIGNvcmVzID0gNCwNCiAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICBzZWVkID0gMiwgZmlsZSA9ICJGaXRzL21hbGVfZml0bmVzcy4wNCIpDQoNCg0KcHJpbnQobWFsZV9maXRuZXNzLjAxKQ0KYGBgDQoNCmBgYHtyfQ0KDQojbWFsZV9maXRuZXNzLjA0IDwtIGFkZF9jcml0ZXJpb24obWFsZV9maXRuZXNzLjA0LCBjcml0ZXJpb24gPSAibG9vIiwgZmlsZSA9ICJmaXRzL21hbGVfZml0bmVzcy4wNCIpDQojbWFsZV9maXRuZXNzLjAxIDwtIGFkZF9jcml0ZXJpb24obWFsZV9maXRuZXNzLjAxLCBjcml0ZXJpb24gPSAid2FpYyIsIGZpbGUgPSAiZml0cy9tYWxlX2ZpdG5lc3MuMDEiKQ0KDQpsb28obWFsZV9maXRuZXNzLjA0KQ0KYGBgDQoNCk5vdGUgdGhhdCB3ZSBubyBsb25nZXIgaGF2ZSBhbnkgdmFsdWVzIHdpdGggaGlnaCBpbmZsdWVuY2UuDQoNCkNvbmR1Y3QgdGhlIHBvc3RlcmlvciBwcmVkaWN0aXZlIGNoZWNrLi4uDQoNCmBgYHtyfQ0KcHBfY2hlY2sobWFsZV9maXRuZXNzLjA0LCB0eXBlID0gImhpc3QiLCBuZHJhd3MgPSAxMSwgYmlud2lkdGggPSAwLjEpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkNCmBgYA0KDQojIyBEZXJpdmUgZXN0aW1hdGVzIGZyb20gcG9zdGVyaW9yDQoNCkdldCBwcmVkaWN0aW9ucyBmcm9tIHRoZSBtb2RlbCBhbmQgcHJlc2VudCB0aGVtIGluIGEgVGFibGUNCg0KYGBge3J9DQoNCmRyYXdzX20gPC0gYXNfZHJhd3NfZGYobWFsZV9maXRuZXNzLjAzKQ0KDQpkcmF3c19tYWxlIDwtDQogIGRyYXdzX20gICU+JSANCiAgbXV0YXRlKGBGZW1hbGUtbGltaXRlZGAgPSBpbnZfbG9naXRfc2NhbGVkKGJfSW50ZXJjZXB0ICsgYl9Fdm9sdXRpb25hcnlfdHJlYXRtZW50RmVtYWxlX2xpbWl0ZWQpLA0KICAgICAgICAgYE1hbGUtbGltaXRlZGAgPSBpbnZfbG9naXRfc2NhbGVkKGJfSW50ZXJjZXB0ICsgYl9Fdm9sdXRpb25hcnlfdHJlYXRtZW50TWFsZV9saW1pdGVkKSwNCiAgICAgICAgIENvbnRyb2wgPSBpbnZfbG9naXRfc2NhbGVkKGJfSW50ZXJjZXB0KSkgJT4lIA0KICBzZWxlY3QoQ29udHJvbCwgYEZlbWFsZS1saW1pdGVkYCwgYE1hbGUtbGltaXRlZGApICU+JSANCiAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoQ29udHJvbCwgYEZlbWFsZS1saW1pdGVkYCwgYE1hbGUtbGltaXRlZGApLA0KICAgICAgICAgICAgICAgICBuYW1lc190byA9ICJFdm9sdXRpb25hcnlfdHJlYXRtZW50IikgJT4lIA0KICByZW5hbWUocHJvcF9mb2NhbF9vZmZzcHJpbmcgPSB2YWx1ZSkNCg0KZHJhd3NfbWFsZSAlPiUgDQogIGdyb3VwX2J5KEV2b2x1dGlvbmFyeV90cmVhdG1lbnQpICU+JSANCiAgc3VtbWFyaXNlKGBFc3RpbWF0ZWQgcHJvcC4gb2Ygb2Zmc3ByaW5nIHNpcmVkYCA9IG1lZGlhbihwcm9wX2ZvY2FsX29mZnNwcmluZyksDQogICAgICAgICAgICBgMi41JWAgPSBxdWFudGlsZShwcm9wX2ZvY2FsX29mZnNwcmluZywgcHJvYnMgPSAwLjAyNSksDQogICAgICAgICAgICBgOTcuNSVgID0gcXVhbnRpbGUocHJvcF9mb2NhbF9vZmZzcHJpbmcsIHByb2JzID0gMC45NzUpKSAlPiUgDQogIHJlbmFtZShgSW5oZXJpdGFuY2UgdHJlYXRtZW50YCA9IEV2b2x1dGlvbmFyeV90cmVhdG1lbnQpICU+JSANCiAgcGFuZGVyKHNwbGl0LmNlbGwgPSA0MCwgc3BsaXQudGFibGUgPSBJbmYsIHJvdW5kID0gMykNCg0KIyBub3cgZmluZCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgY29udHJvbCBhbmQgdGhlIHNleC1saW1pdGVkIEV2b2x1dGlvbl90cmVhdG1lbnRzDQoNCiMgdGhlIGludl9sb2dpdF9zY2FsZWQoKSBmdW5jdGlvbiBjb252ZXJ0cyB0aGUgcG9zdGVyaW9yIGRyYXdzIG9udG8gdGhlIHJlc3BvbnNlIHNjYWxlIA0KDQpkcmF3c19tICU+JSANCiAgbXV0YXRlKHBfY29udHJvbCA9ICBpbnZfbG9naXRfc2NhbGVkKGJfSW50ZXJjZXB0KSwNCiAgICAgICAgIHBfZmVtYWxlID0gaW52X2xvZ2l0X3NjYWxlZChiX0V2b2x1dGlvbmFyeV90cmVhdG1lbnRGZW1hbGVfbGltaXRlZCArIGJfSW50ZXJjZXB0KSwNCiAgICAgICAgIHBfbWFsZSA9IGludl9sb2dpdF9zY2FsZWQoYl9Fdm9sdXRpb25hcnlfdHJlYXRtZW50TWFsZV9saW1pdGVkICsgYl9JbnRlcmNlcHQpLA0KICAgICAgICAgYEZlbWFsZS1saW1pdGVkYCA9IHBfZmVtYWxlIC8gcF9jb250cm9sLA0KICAgICAgICAgYE1hbGUtbGltaXRlZGAgPSBwX21hbGUgLyBwX2NvbnRyb2wpICU+JSANCiAgZ2F0aGVyKGtleSA9IGBkaWZmZXJlbmNlIGNvbXBhcmlzb25gLCB2YWx1ZSA9IGAlIGRpZmZlcmVuY2VgKSAlPiUgDQogIGZpbHRlcihgZGlmZmVyZW5jZSBjb21wYXJpc29uYCA9PSBjKCJGZW1hbGUtbGltaXRlZCIsICJNYWxlLWxpbWl0ZWQiKSkgJT4lIA0KICBncm91cF9ieShgZGlmZmVyZW5jZSBjb21wYXJpc29uYCkgICU+JSANCiAgc3VtbWFyaXNlKGBNZWFuIHByb3BvcnRpb24gb2Ygb2Zmc3ByaW5nIHNpcmVkIHJlbGF0aXZlIHRvIGNvbnRyb2xgICA9IG1lYW4oYCUgZGlmZmVyZW5jZWApLA0KICAgICAgICAgICAgYDIuNSVgID0gcXVhbnRpbGUoYCUgZGlmZmVyZW5jZWAsIHByb2JzID0gMC4wMjUpLA0KICAgICAgICAgICAgYDk3LjUlYCA9IHF1YW50aWxlKGAlIGRpZmZlcmVuY2VgLCBwcm9icyA9IDAuOTc1KSkgJT4lIA0KICByZW5hbWUoYEluaGVyaXRhbmNlIHRyZWF0bWVudGAgPSBgZGlmZmVyZW5jZSBjb21wYXJpc29uYCkgJT4lIA0KICBwYW5kZXIoc3BsaXQuY2VsbCA9IDQwLCBzcGxpdC50YWJsZSA9IEluZiwgcm91bmQgPSAzKQ0KYGBgDQoNCiMgQnVpbGRpbmcgRmlndXJlIDENCg0KYGBge3J9DQoNCiMgZmVtYWxlIHBsb3RzDQoNCmZfMSA8LQ0KICBkcmF3c19mZW1hbGUgJT4lIA0KICBnZ3Bsb3QoYWVzKEV2b2x1dGlvbmFyeV90cmVhdG1lbnQsIHByb3BfZm9jYWxfb2Zmc3ByaW5nKSkgKyANCiAgc3RhdF9leWUoYWVzKGZpbGwgPSBFdm9sdXRpb25hcnlfdHJlYXRtZW50KSwgLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAxKSArICMgd2lkdGggaW5kaWNhdGVzIHRoZSB1bmNlcnRhaW50eSBpbnRlcnZhbHM6IGhlcmUgd2UgaGF2ZSA2NiUgYW5kIDk1JSBpbnRlcnZhbHMNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMykpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKCJGZW1hbGUgZml0bmVzc1xuKHByb3BvcnRpb24gb2Ygb2Zmc3ByaW5nIHByb2R1Y2VkKSIsDQogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKDAuNywgMC44KSkgKw0KICAjY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAuNCwgMSkpICsNCiAgeGxhYihOVUxMKSArDQogIHRoZW1lX2J3KCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQ0KDQpmXzIgPC0NCiAgZHJhd3MgJT4lIA0KICBtdXRhdGUoYEZlbWFsZS1saW1pdGVkYCA9IGJfRXZvbHV0aW9uYXJ5X3RyZWF0bWVudEZlbWFsZV9saW1pdGVkLA0KICAgICAgICAgYE1hbGUtbGltaXRlZGAgPSBiX0V2b2x1dGlvbmFyeV90cmVhdG1lbnRNYWxlX2xpbWl0ZWQpICU+JSANCiAgZ2F0aGVyKGtleSA9IHBhcmFtZXRlciwgdmFsdWUgPSBsb2dvZGRzKSAlPiUgDQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gYygiRmVtYWxlLWxpbWl0ZWQiLCAiTWFsZS1saW1pdGVkIikpICU+JQ0KICBhc190aWJibGUoKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHBhcmFtZXRlciwgbG9nb2RkcykpICsgDQogIHN0YXRfaGFsZmV5ZShhZXMoZmlsbCA9IHBhcmFtZXRlciksIC53aWR0aCA9IGMoMC42NiwgMC45NSkpICsgIyB3aWR0aCBpbmRpY2F0ZXMgdGhlIHVuY2VydGFpbnR5IGludGVydmFsczogaGVyZSB3ZSBoYXZlIDY2JSBhbmQgOTUlIGludGVydmFscw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGZW1hbGUtbGltaXRlZCIgPSAiI2ZmZDA2ZiIsICJNYWxlLWxpbWl0ZWQiID0gIiM3MmJjZDUiKSkgKyANCiAgY29vcmRfZmxpcCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKC0xLCAwLCAxKSkgKw0KICB4bGFiKE5VTEwpICsNCiAgeWxhYihOVUxMKSArDQogIHRoZW1lX2J3KCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQ0KDQojIG1hbGUgcGxvdHMNCg0KZl8zIDwtDQogIGRyYXdzX21hbGUgJT4lIA0KICBnZ3Bsb3QoYWVzKEV2b2x1dGlvbmFyeV90cmVhdG1lbnQsIHByb3BfZm9jYWxfb2Zmc3ByaW5nKSkgKyANCiAgc3RhdF9leWUoYWVzKGZpbGwgPSBFdm9sdXRpb25hcnlfdHJlYXRtZW50KSwgLndpZHRoID0gYygwLjY2LCAwLjk1KSwgYWxwaGEgPSAxKSArICMgd2lkdGggaW5kaWNhdGVzIHRoZSB1bmNlcnRhaW50eSBpbnRlcnZhbHM6IGhlcmUgd2UgaGF2ZSA2NiUgYW5kIDk1JSBpbnRlcnZhbHMNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiSGlyb3NoaWdlIiwgMykpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKCJNYWxlIGZpdG5lc3Ncbihwcm9wb3J0aW9uIG9mIG9mZnNwcmluZyBzaXJlZCkiLA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygwLjQsIDAuNiwgMC44KSkgKw0KICAjY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAuNCwgMSkpICsNCiAgeGxhYigiSW5oZXJpdGFuY2UgdHJlYXRtZW50IikgKw0KICB0aGVtZV9idygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KZl80IDwtDQogIGRyYXdzX20gJT4lIA0KICBtdXRhdGUoYEZlbWFsZS1saW1pdGVkYCA9IGJfRXZvbHV0aW9uYXJ5X3RyZWF0bWVudEZlbWFsZV9saW1pdGVkLA0KICAgICAgICAgYE1hbGUtbGltaXRlZGAgPSBiX0V2b2x1dGlvbmFyeV90cmVhdG1lbnRNYWxlX2xpbWl0ZWQpICU+JSANCiAgZ2F0aGVyKGtleSA9IHBhcmFtZXRlciwgdmFsdWUgPSBsb2dvZGRzKSAlPiUgDQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gYygiRmVtYWxlLWxpbWl0ZWQiLCAiTWFsZS1saW1pdGVkIikpICU+JQ0KICBhc190aWJibGUoKSAlPiUgDQogICNtdXRhdGUocGFyYW1ldGVyID1mYWN0b3IocGFyYW1ldGVyLCBsZXZlbHM9YygiU0QtTWFkIiwgIlNELTcyIiwgIlNELTUiKSkpICU+JQ0KICANCiAgZ2dwbG90KGFlcyhwYXJhbWV0ZXIsIGxvZ29kZHMpKSArIA0KICBzdGF0X2hhbGZleWUoYWVzKGZpbGwgPSBwYXJhbWV0ZXIpLCAud2lkdGggPSBjKDAuNjYsIDAuOTUpKSArICMgd2lkdGggaW5kaWNhdGVzIHRoZSB1bmNlcnRhaW50eSBpbnRlcnZhbHM6IGhlcmUgd2UgaGF2ZSA2NiUgYW5kIDk1JSBpbnRlcnZhbHMNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiRmVtYWxlLWxpbWl0ZWQiID0gIiNmZmQwNmYiLCAiTWFsZS1saW1pdGVkIiA9ICIjNzJiY2Q1IikpICsgDQogIGNvb3JkX2ZsaXAoeWxpbSA9IGMoLTEsIDEpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygtMSwgMCwgMSkpICsNCiAgeGxhYihOVUxMKSArDQogIHlsYWIoIkxvZy1vZGRzIG1lYW4gZGlmZmVyZW5jZSBmcm9tIGNvbnRyb2wiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQ0KDQoNCihmXzEgKyBmXzIpIC8oZl8zICsgZl80KQ0KDQpgYGANCg0KKipGaWd1cmUgMSoqOiAqKmEqKiBzaG93cyB0aGUgZXN0aW1hdGVkIG1lYW4gZmVtYWxlIGZpdG5lc3MgZm9yIGZsaWVzIGNhcnJ5aW5nIGF1dG9zb21lcyB0aGF0IGhhZCBwcmV2aW91c2x5IGV4cGVyaWVuY2VkIHVuY29uc3RyYWluZWQgaW5oZXJpdGFuY2UgKGNvbnRyb2wpLCBmZW1hbGUtbGltaXRlZCBpbmhlcml0YW5jZSBvciBtYWxlLWxpbWl0ZWQgaW5oZXJpdGFuY2UuICoqYioqIHNob3dzIHRoZSBsb2ctb2RkcyBtZWFuIGRpZmZlcmVuY2UgaW4gbWVhbnMgYmV0d2VlbiB0aGUgc2V4LWxpbWl0ZWQgdHJlYXRtZW50cyBhbmQgdGhlIGNvbnRyb2wgZXZvbHV0aW9uYXJ5IHRyZWF0bWVudC4gKipjKiogYW5kICoqZCoqIGRlcGljdCB0aGUgc2FtZSB0aGluZ3MgYXMgKiphKiogYW5kICoqYioqLCBleGNlcHQgZm9yIGVzdGltYXRlZCBtZWFuIG1hbGUgZml0bmVzcy4NCg0K